首页 > 解决方案 > 使用自定义处理程序测试 API 端点时无法访问多路复用器参数

问题描述

我的 API 端点有一个自定义处理程序,如下所示:

type HTTPError struct {
    Error   error
    Message string
    Code    int
}

type endpointREST func(http.ResponseWriter, *http.Request) *HTTPError

func (fn endpointREST) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if e := fn(w, r); e != nil {
        http.Error(w, e.Message, e.Code)
    }
}

我的示例路线如下所示:

func GetShare(w http.ResponseWriter, r *http.Request) *HTTPError {
    vars := mux.Vars(r)
    fmt.Println(r.URL)  // http://127.0.0.1:36455/share/5713d228-a042-446d-a5e4-183b19fa832a
    fmt.Println(vars)  // -->> always empty map when testing 
    return nil
}

这些路线在设置后运行良好(手动,使用邮递员)

router := mux.NewRouter().StrictSlash(true)
handler := cors.Default().Handler(router)
router.Handle("/share/{id}", endpointREST(GetShare)).Methods("GET")
log.Fatal(http.ListenAndServe(":6969", handler))

问题是,我无法以这种方式测试 API,因为mux.Vars(r)在测试环境中总是会返回一个空地图。

这是我的测试代码:

func TestGetShare(t *testing.T) {
    Reset()
    router := mux.NewRouter()
    ts := httptest.NewServer(router)
    router.Handle("/share/{id}", endpointREST(GetShare)).Methods("GET")
    defer ts.Close()

    t.Run("unauthorized", func(t *testing.T) {
        req, _ := http.NewRequest("GET", ts.URL + "/share/5713d228-a042-446d-a5e4-183b19fa832a", nil)
        res, _ := http.DefaultClient.Do(req)
        assert.Equal(t, http.StatusUnauthorized, res.StatusCode)
    })
}

标签: apirestgotesting

解决方案


我建议你使用SetURLVars 测试助手函数

// SetURLVars sets the URL variables for the given request, to be accessed via
// mux.Vars for testing route behaviour. Arguments are not modified, a shallow
// copy is returned.
//
// This API should only be used for testing purposes; it provides a way to
// inject variables into the request context. Alternatively, URL variables
// can be set by making a route that captures the required variables,
// starting a server and sending the request to that server.
func SetURLVars(r *http.Request, val map[string]string) *http.Request {
    return requestWithVars(r, val)
}

推荐阅读