【问题标题】:Unit Testing App Engine with Gorilla MUX使用 Gorilla MUX 对 App Engine 进行单元测试
【发布时间】:2016-11-22 04:54:42
【问题描述】:

我想为 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
}

问题是处理程序总是看到一个空的“电子邮件”参数,因为 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 单元测试的内容。

【问题讨论】:

    标签: unit-testing google-app-engine go mux


    【解决方案1】:

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

    ma​​in.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)
    }
    

    ma​​in_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 路由,因为这不是您的测试的一部分,但想法是一样的。为简单起见,也没有检查错误。

    【讨论】:

    • 感谢您的回复!我认为这行得通。起初我以为您建议我必须更改处理程序,但仔细阅读后,它只是有助于证明该值被正确读取。我做了一个快速检查,它似乎工作。如果有任何问题,我会将其标记为答案并更新。
    • 太棒了.. 是的,处理程序是相同的,唯一的区别在于测试,与您所拥有的相比非常小。您只需创建您的多路复用路由器 (makeRouter) 并使用您的测试请求 (req) 和记录器 (rec) 在其上调用 ServeHTTP,而不是直接调用处理程序。祝你好运!
    猜你喜欢
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    相关资源
    最近更新 更多