doulu7921 2016-07-19 10:36
浏览 46
已采纳

使用Gorilla MUX的单元测试App Engine

I want to write tests for handlers in Google App Engine that use Gorilla mux to read variables from the request URL.

I understand from the documentation that you can create a fake context and request to use with testing.

I'm calling the handler directly in the test but the handler isn't seeing the path parameter as expected.

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
}

The problem is that the handler always sees an empty "email" parameter because the path is not interpreted by Gorilla mux.

The router is as below:

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
}

All my searches have not gotten anything specific to App Engine unit testing with Gorilla mux.

  • 写回答

1条回答 默认 最新

  • dqn8235 2016-10-14 19:41
    关注

    Since what you're testing is the handler, you could just get an instance of the router and call ServeHTTP on it. Here is how it should be based on your code.

    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)
        }
    }
    

    Notice I removed the rest routes since that's not part of your test, but the idea would be the same. Also didn't check for errors for simplicity.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来