【问题标题】:Mocking functions for handler unit test处理程序单元测试的模拟函数
【发布时间】:2018-07-22 15:02:57
【问题描述】:

我被模拟测试卡住了,这是我的处理程序路线:

r.Handle("/users/{userID}", negroni.New(
        negroni.HandlerFunc(validateTokenMiddleware),
        negroni.Wrap(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            getUserDetailsHandler(w, r, db)
        })),
    )).Methods("GET")

这是我的处理程序:

func getUserDetailsHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) {

    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

    //Create UserDetailsView instance
    var userview UserDetailsView

    //Get varibale from mux
    vars := mux.Vars(r)

    //UserID  fetches userId from vars
    userID := vars["userID"]

    //Get user Information by wpUsersID
    wuis := store.NewWpUserInformationStore(db)
    userInformation, _:= wuis.GetByID(uID)


        json.NewEncoder(w).Encode(userview); 

        //Print result
        w.WriteHeader(http.StatusOK)
}

我模拟了存储包中名为GetByID 的函数,它看起来像这样:

type wpUserInfoMockStore struct {
    mock.Mock
}

func (m *wpUserInfoMockStore) GetByID(user *WpUserInformation) error {
    rets := m.Called(user)
    return rets.Error(0)
}

//InitMockStore store
func InitMockStore() *wpUserInfoMockStore {
    s := new(wpUserInfoMockStore)
    //store = s
    return s
}

我为处理程序编写测试用例,但出现错误cannot convert getUserDetailsHandler (type func(http.ResponseWriter, *http.Request, *sql.DB)) to type http.HandlerFunc,但我找不到它发生的原因,这里我使用此https://github.com/sohamkamani/blog_example__go_web_db 的参考,这是我的测试用例代码:

func TestGetUserDetailsTes(t *testing.T) {

    // Initialize the mock store
    mockStore := store.InitMockStore()

    mockStore.On("GetByID").Return([]*store.WpUserInformation{{
        21,
        sql.NullString{String: "john"},
        sql.NullString{String: "Sorensen"},
        0}}, nil).Once()

    req, err := http.NewRequest("GET", "", nil)

    //if requests gives error
    if err != nil {
        panic(err.Error())
    }

    //parameters for generateTestUserJWT are set
    testUser.ID = "22"
    testUser.UserName = "johns"
    testUser.Depot = "NYC"

    //JWT generated
    refToken, err := generateTestJWT(testUser, false)

    //handling error while generating token
    if err != nil {
        panic(err.Error())
    }

    //token returned is concatenated with Bearer string
    newToken = "Bearer " + refToken

    //request authorization header is set
    req.Header.Set("Authorization", newToken)
    req.Header.Set("Latitude", "123.12")
    req.Header.Set("Longitude", "456.45")

    //response is set
    w := httptest.NewRecorder()

    hf := http.HandlerFunc(getUserDetailsHandler)

    hf.ServeHTTP(w, req)

    //if response code is not statusOK then test fails
    if w.Code != http.StatusOK {
        t.Errorf("/users/{userID} GET request failed, got: %d, want: %d.", w.Code, http.StatusOK)
    }
}

如您所见,我测试了没有像 req, err := http.NewRequest("GET", "", nil) 这样的 URL 的处理程序,但是当我在内部使用链接时,我无法使用模拟函数,这里我缺少什么/错误请帮助我。 谢谢。

【问题讨论】:

  • 测试中hf := http.HandlerFunc(getUserDetailsHandler) 所在的行导致了恐慌,这应该从您未包含的堆栈跟踪中清楚地看出。现在它出现恐慌的原因是因为您的 getUserDetailsHandler 函数的签名与 http.HandlerFunc 函数类型的签名不同。所以基本上你有两种不同的类型,你试图将一种转换为另一种,这是不可能的,所以你会感到恐慌。
  • 我该如何解决这个问题,请您编写一些代码来从测试用例调用处理程序。谢谢。
  • 实际上,如果函数 store.NewWpUserInformationStore(db) 已经返回使用 mockStore 实例的内容,您应该能够做到这一点 play.golang.org/p/_cFR3vyjkPr。但是正如您从代码示例中看到的那样,为了避免恐慌,您只需将处理程序包装在一个函数中,就像您在问题顶部的代码 sn-p 中所做的那样。

标签: unit-testing go mocking


【解决方案1】:

使用中间件处理程序来生成函数。在你的主函数中传递一个处理程序,它将调用你的中间件返回http.handler。这样您就可以将 db 对象传递给您的主要数据,这将调用中间件返回处理程序。

func getUserDetailsHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) http.HandlerFunc{

    return func(w http.ResponseWriter, r *http.Request) {

        w.Header().Set("Content-Type", "application/json; charset=UTF-8")

        //Create UserDetailsView instance
        var userview UserDetailsView

        //Get varibale from mux
        vars := mux.Vars(r)

        //UserID  fetches userId from vars
        userID := vars["userID"]

        //Get user Information by wpUsersID
        wuis := store.NewWpUserInformationStore(db)
        userInformation, _:= wuis.GetByID(uID)


        json.NewEncoder(w).Encode(userview); 

        //Print result
        w.WriteHeader(http.StatusOK)
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多