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.

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

    报告相同问题?

    悬赏问题

    • ¥15 寻涂色内存脚本作者有项目有市场有资源.却技术
    • ¥15 蓝桥杯c51单片机问题
    • ¥15 ajax跨域问题请求修改代码
    • ¥15 python matplotlib
    • ¥15 短信测压+语音,有偿,必须用Python
    • ¥20 COCOS2DX的protobuf协议注册函数问题
    • ¥15 (标签-Pytorch|关键词-Stream)
    • ¥15 求深圳2019年开放数据应用创新大赛的营运车辆数据!
    • ¥15 软件UI界面绘制折线图
    • ¥20 用c语言写一个团队考勤系统