httptestでWriteHeaderができなかった話
はじめに goでhttpのhandlerのテストを書いているときに詰まったところを書きます。 詰まったところは、httptest.NewRecoder()の再利用ができなかったことです。 正確には、再利用する方法はあるかもしれないがよくわからなかったので、再度NewRecoder()を呼び出して、新規作成した、で解決しました。
内容
package mytest import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestOverride(t *testing.T) { handler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { var js map[string]interface{} decoder := json.NewDecoder(req.Body) if err := decoder.Decode(&js); err == nil { if js["msg"] == "error" { res.WriteHeader(http.StatusBadRequest) res.Write([]byte(`{"result": false}`)) } else { res.WriteHeader(http.StatusOK) res.Write([]byte(`{"result": true}`)) } } }) // 1: StatusOK jsons := `{"msg": "test"}` w := httptest.NewRecorder() r, err := newRequest([]byte(jsons), "POST", "application/json") if err != nil { t.Errorf("%s", err) } handler.ServeHTTP(w, r) if w.Code != http.StatusOK { t.Errorf("Expected status code is 200 but got %d", w.Code) } // 2: BadRequest error code jsons = `{"msg": "error"}` w = httptest.NewRecorder() // ここで再度NewRecoder()を呼ぶ r, err = newRequest([]byte(jsons), "POST", "application/json") if err != nil { t.Errorf("%s", err) } handler.ServeHTTP(w, r) if w.Code == http.StatusOK { t.Errorf("Expected status code is NOT 200 but got %d", w.Code) } } func newRequest(data []byte, method string, c string) (*http.Request, error) { req, err := http.NewRequest( method, "", bytes.NewBuffer([]byte(data)), ) req.Header.Set("Content-Type", c) return req, err }
上記は、テストが通ります。
はじめは、コメント部分をw.Body.Reset()をすれば大丈夫なのかなぁと安易にやったのですが、そうするとHeader部分への上書きはできませんでした。おそらく、GOの公式ドキュメントに記載されている内容なのかと思います。したがって、w.Body.Reset()で行うと、2回目のBadRequestのエラーを期待するのですが200が返ってくる結果となってしまいます。