0

Gorilla mux を使用してリクエスト URL から変数を読み取る Google App Engine のハンドラーのテストを作成したいと考えています。

ドキュメントから、偽のコンテキストを作成し、テストで使用するように要求できることを理解しています。

テストでハンドラーを直接呼び出していますが、ハンドラーはパス パラメーターを期待どおりに認識していません。

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 によって解釈されないため、ハンドラーが常に空の「email」パラメーターを参照することです。

ルーターは以下の通りです。

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 単体テストに固有のものは得られませんでした。

4

1 に答える 1

0

テストしているのはハンドラーなので、ルーターのインスタンスを取得して、それに対して 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テストの一部ではないため、ルートを削除したことに注意してください。ただし、考え方は同じです。また、簡単にするためにエラーをチェックしませんでした。

于 2016-10-14T19:41:54.930 に答える