如何正确测试调用其中的另一个函数的处理程序

时间:2017-08-21 00:19:21

标签: unit-testing go

我希望测试看起来像这样的PostUser函数(为简单起见省略了错误处理):

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 to be more than 2 characters and less than 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 to be more at least 8 characters")}
    }

    hashedPassword,_ := bcrypt.GenerateFromPassword([]byte(user.Password), 12)


    env.DB.InsertUser(user.Username, hashedPassword, user.Email) // need to mock this out


    userData,_ := json.Marshal(user)


    defer req.Body.Close()

    w.Write(userData)

    return nil
}

我的env.go文件如下所示:

type Env struct {
    DB *db.DB
}

我的db.go文件如下所示:

type DB struct {
    Session *mgo.Session
}

如何通过我的DB结构模拟InsertUser调用,以便我可以对PostUser进行单元测试?

1 个答案:

答案 0 :(得分:0)

要使用模拟测试,您需要创建模拟可以实现的接口。当然,您替换模拟的结构也需要实现接口的所有方法,以便它们可以自由地互换。

例如,您可以拥有一个界面:

type DBInterface interface {
    InsertUser(string, string, string)
    //all other methods on the DB struct here  
}

然后你的DB结构已经实现了接口的所有方法。从那里你可以创建一个也实现接口的模拟结构。

type DBMock struct {}

func (dbm *DBMock) InsertUser(username, password, email string) {
    //whatever mock functionality you want here
    return
} 

//all other methods also implemented.

然后你可以改变env以获得指向DBInterface而不是DB的指针。当您设置要传递给处理程序的env时,在生产版本中使用DB结构并在测试中使用DBMock结构。

相关问题