unit testing - How to properly test a handler that calls another function inside of it -
i looking test postuser function looks (error handling omitted simplicity):
func postuser(env *env, w http.responsewriter, req *http.request) error { decoder := json.newdecoder(req.body) decoder.decode(&user) if len(user.username) < 2 || len(user.username) > 30 { return statuserror{400, errors.new("usernames need more 2 characters , less 30 characters")} } emailre := regexp.mustcompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`) if !emailre.matchstring(user.email) { return statuserror{400, errors.new("invalid email address")} } if len(user.password) < 8 { return statuserror{400, errors.new("passwords need more @ least 8 characters")} } hashedpassword,_ := bcrypt.generatefrompassword([]byte(user.password), 12) env.db.insertuser(user.username, hashedpassword, user.email) // need mock out userdata,_ := json.marshal(user) defer req.body.close() w.write(userdata) return nil }
my env.go
file looks this:
type env struct { db *db.db }
my db.go
file looks this:
type db struct { session *mgo.session }
how mock insertuser call db struct, can unit test postuser?
to use mocks testing need create interface mock can implement. naturally, struct you're replacing mock needs implement methods of interface freely interchangeable.
for example, have interface:
type dbinterface interface { insertuser(string, string, string) //all other methods on db struct here }
then db struct implements methods of interface. there can create mock struct implements interface.
type dbmock struct {} func (dbm *dbmock) insertuser(username, password, email string) { //whatever mock functionality want here return } //all other methods implemented.
then can alter env have pointer dbinterface instead of db. when setup env passed handler, in production version use db struct , in testing use dbmock struct.
Comments
Post a Comment