--- FAIL: TestServer (0.00s)--- FAIL: TestServer/tells_store_to_cancel_work_if_request_is_cancelled (0.00s) context_test.go:62: store was not told to cancel
func (s *SpyStore) assertWasCancelled() { s.t.Helper()if!s.cancelled { s.t.Errorf("store was not told to cancel") }}func (s *SpyStore) assertWasNotCancelled() { s.t.Helper()if s.cancelled { s.t.Errorf("store was told to cancel") }}
スパイを作成するときは、*testing.Tを渡すことを忘れないでください。
funcTestServer(t *testing.T) { data :="hello, world" t.Run("returns data from store", func(t *testing.T) { store :=&SpyStore{response: data, t: t} svr := Server(store) request := httptest.NewRequest(http.MethodGet, "/", nil) response := httptest.NewRecorder() svr.ServeHTTP(response, request)if response.Body.String() != data { t.Errorf(`got "%s", want "%s"`, response.Body.String(), data) } store.assertWasNotCancelled() }) t.Run("tells store to cancel work if request is cancelled", func(t *testing.T) { store :=&SpyStore{response: data, t: t} svr := Server(store) request := httptest.NewRequest(http.MethodGet, "/", nil) cancellingCtx, cancel := context.WithCancel(request.Context()) time.AfterFunc(5*time.Millisecond, cancel) request = request.WithContext(cancellingCtx) response := httptest.NewRecorder() svr.ServeHTTP(response, request) store.assertWasCancelled() })}
funcServer(store Store) http.HandlerFunc {returnfunc(w http.ResponseWriter, r *http.Request) { }}
SpyStoreを更新します
typeSpyStorestruct { response string t *testing.T}func (s *SpyStore) Fetch(ctx context.Context) (string, error) { data :=make(chanstring, 1)gofunc() {var result stringfor _, c :=range s.response {select {case<-ctx.Done(): s.t.Log("spy store got cancelled")returndefault: time.Sleep(10* time.Millisecond) result +=string(c) } } data <- result }()select {case<-ctx.Done():return"", ctx.Err()case res :=<-data:return res, nil }}
t.Run("tells store to cancel work if request is cancelled", func(t *testing.T) { store :=&SpyStore{response: data, t: t} svr := Server(store) request := httptest.NewRequest(http.MethodGet, "/", nil) cancellingCtx, cancel := context.WithCancel(request.Context()) time.AfterFunc(5*time.Millisecond, cancel) request = request.WithContext(cancellingCtx) response :=&SpyResponseWriter{} svr.ServeHTTP(response, request)if response.written { t.Error("a response should not have been written") }})
テストを実行してみます
=== RUN TestServer
=== RUN TestServer/tells_store_to_cancel_work_if_request_is_cancelled
--- FAIL: TestServer (0.01s)
--- FAIL: TestServer/tells_store_to_cancel_work_if_request_is_cancelled (0.01s)
context_test.go:47: a response should not have been written
成功させるのに十分なコードを書く
funcServer(store Store) http.HandlerFunc {returnfunc(w http.ResponseWriter, r *http.Request) { data, err := store.Fetch(r.Context())if err !=nil {return// todo: log error however you like } fmt.Fprint(w, data) }}