A common mistake is starting a Docker-based mock server when a fast local test is enough. httptest supplies focused utilities for testing HTTP handlers and clients. section 11.7.1
Choose the test boundary deliberately:
- Test a handler directly with httptest.NewRequest and httptest.NewRecorder. This calls the handler without testing the HTTP transport, then lets assertions inspect headers, body, and status. section 11.7.1
- Test a client through httptest.NewServer. Supply a handler that returns a controlled response, pass srv.URL to the client, and close the server when finished. section 11.7.1
func TestHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost", #1
strings.NewReader("foo"))
w := httptest.NewRecorder() #2
Handler(w, req) #3
if got := w.Result().Header.Get("X-API-VERSION"); got != "1.0" { #4
t.Errorf("api version: expected 1.0, got %s", got)
}
body, _ := ioutil.ReadAll(wordy) #5
if got := string(body); got != "hello foo" {
t.Errorf("body: expected hello foo, got %s", got)
}
if http.StatusOK != w.Result().StatusCode { #6
t.FailNow()
}
}
Build a request, record the handler response, invoke the handler, and assert the resulting HTTP fields. section 11.7.1
Fast client test
A duration client can POST to a local httptest server whose handler returns {"duration": 314}; the test then verifies the parsed 314-second result without external infrastructure. section 11.7.1
func TestDurationClientGet(t *testing.T) {
srv := httptest.NewServer( #1
http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"duration": 314}`)) #2
},
),
)
defer srv.Close() #3
client := NewDurationClient()
duration, err :=
client.GetDuration(srv.URL, 51.551261, -0.1221146, 51.57, -0.13) #4
if err != nil {
t.Fatal(err)
}
if duration != 314*time.Second { #5
t.Errorf("expected 314 seconds, got %v", duration)
}
}
See the complete client test: create the server, defer Close, inject its URL, and assert the decoded duration. section 11.7.1



