httptest.Serverとhttptest.ResponseRecorderの使い分け
環境
httptest.Serverとhttptest.ResponseRecorder
- ServerとResponseRecorderは何が違うのか?どう使い分けるのか?
- 答え:When to use httptest.Server and httptest.ResponseRecorder
httptest.Server
- httptest.Serverは外部のHTTPサーバと通信を行うコードをテストするために利用する(外部APIの挙動のエミュレート)
- クライアント-サーバモデルで言うと、テストしたい対象がクライアントの場合に相当する模様
httptestパッケージより引用
package main import ( "fmt" "io/ioutil" "log" "net/http" "net/http/httptest" ) func main() { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, client") })) defer ts.Close() res, err := http.Get(ts.URL) if err != nil { log.Fatal(err) } greeting, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { log.Fatal(err) } fmt.Printf("%s", greeting) }
httptest.NewRecorder
- httptest.NewRecorderは純粋にHTTPリクエストに対するハンドラーの動作をテストするために利用する
- 例えばHello worldを返すだけのWebサーバのコードを書いた場合のテストコードはhttptest.NewRecorderで十分
httptestパッケージより引用
package main import ( "fmt" "io" "io/ioutil" "net/http" "net/http/httptest" ) func main() { handler := func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "<html><body>Hello World!</body></html>") } req := httptest.NewRequest("GET", "http://example.com/foo", nil) w := httptest.NewRecorder() handler(w, req) resp := w.Result() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(resp.StatusCode) fmt.Println(resp.Header.Get("Content-Type")) fmt.Println(string(body)) }
関連:NewRecorderを利用する場合にserveHTTPを使用する必要があるのか
http.HandlerFunc(articlesHandler).ServeHTTP(rr, req)
してレスポンスを検証している例もある- 例えばTesting HTTP handlers in Goや他の書籍のサンプルコードにもあった
- マルチプレクサ経由でhandlerを呼び出している(HandleFuncはマルチプレクサ(ServeMux)を返し、ServeHTTPはマルチプレクサに登録されているパターンにマッチするハンドラを呼び出す)
- 結局テストコード中でハンドラを登録しているなら初めからServerを使うか、ハンドラの処理だけにフォーカスするかした方が良いのではないか?(Goのhttpパッケージをテストしたいわけではない)