使用 Gorilla MUX 对 App Engine 进行单元测试

Unit Testing App Engine with Gorilla MUX

我想为 Google App Engine 中的处理程序编写测试,这些处理程序使用 Gorilla mux 从请求中读取变量 URL。

我从 documentation 了解到您可以创建一个虚假的上下文并请求用于测试。

我在测试中直接调用处理程序,但处理程序没有按预期看到路径参数。

func TestRouter(t *testing.T) {
  inst, _ := aetest.NewInstance(nil) //ignoring error for brevity
  defer inst.Close()
  //tried adding this line because the test would not work with or without it
  httptest.NewServer(makeRouter())
  req, _ := inst.NewRequest("GET", "/user/john@example.com/id-123", nil)
  req.Header.Add("X-Requested-With", "XMLHttpRequest")
  resp := httptest.NewRecorder()
  restHandler(resp, req)
}

func restHandler(w http.ResponseWriter, r *http.Request) {
  ctx := appengine.NewContext(r)
  params := mux.Vars(r)
  email := params["email"]
  //`email` is always empty
}

问题是处理程序总是看到一个空的 "email" 参数,因为 Gorilla mux 不解释该路径。

路由器如下:

func makeRouter() *mux.Router {
  r := mux.Router()
  rest := mux.NewRouter().Headers("Authorization", "").
    PathPrefix("/api").Subrouter()

  app := r.Headers("X-Requested-With", "XMLHttpRequest").Subrouter()
  app.HandleFunc("/user/{email}/{id}", restHandler).Methods(http.MethodGet)

  //using negroni for path prefix /api
  r.PathPrefx("/api").Handler(negroni.New(
    negroni.HandlerFunc(authCheck), //for access control
    negroni.Wrap(rest),
  ))
  return r
}

我的所有搜索都没有得到任何特定于使用 Gorilla mux 进行 App Engine 单元测试的信息。

由于您要测试的是处理程序,您可以只获取路由器的一个实例并在其上调用 ServeHTTP。这是它应该如何基于您的代码。

main.go

func init() {
    r := makeRouter()
    http.Handle("/", r)
}

func makeRouter() *mux.Router {
    r := mux.NewRouter()
    app := r.Headers("X-Requested-With", "XMLHttpRequest").Subrouter()
    app.HandleFunc("/user/{email}/{id}", restHandler).Methods(http.MethodGet)

    return r
}

func restHandler(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    email := params["email"]
    fmt.Fprintf(w, email)
}

main_test.go

func TestRouter(t *testing.T) {
    inst, _ := aetest.NewInstance(nil) //ignoring error for brevity
    defer inst.Close()

    req, _ := inst.NewRequest("GET", "/user/john@example.com/id-123", nil)
    req.Header.Add("X-Requested-With", "XMLHttpRequest")
    rec := httptest.NewRecorder()

    r := makeRouter()
    r.ServeHTTP(rec, req)

    if email := rec.Body.String(); email != "john@example.com" {
        t.Errorf("router failed, expected: %s, got: %s", "john@example.com", email)
    }
}

请注意,我删除了 rest 路线,因为那不是您测试的一部分,但想法是一样的。也没有为简单起见检查错误。