Simplify handler testing by introducing test helpers. Focus on quality error messages. This design takes inspiration from Bertrand Meyers, Design by Contract
package example
// ... imports hidden for brevity ...
func Test_helloWorld(t *testing.T) {
// require
h := helloWorld()
r := httptest.NewRequest("GET", "/", http.NoBody)
// do
resp := recordResp(h, r)
data := readBody(resp)
// ensure
ensure(t,
statusCodeIs(resp.StatusCode, 201),
bodyContains(data, "Hello", "space"),
)
}
Compile and test your code
$ go test .
--- FAIL: Test_helloWorld (0.00s)
helloworld_test.go:21: status code 200, expected 201
helloworld_test.go:21: body missing ["space"]
func recordResp(h http.Handler, r *http.Request) *http.Response {
w := httptest.NewRecorder()
h.ServeHTTP(w, r)
return w.Result()
}
func readBody(resp *http.Response) string {
data, _ := ioutil.ReadAll(resp.Body)
return string(data)
}
func ensure(t *testing.T, errors ...error) {
t.Helper()
for _, err := range errors {
if err != nil {
t.Error(err)
}
}
}
func statusCodeIs(got, exp int) error {
if err := equals(got, exp); err != nil {
return fmt.Errorf("status code %w", err)
}
return nil
}
func bodyContains(body string, phrases ...string) error {
if err := contains(body, phrases...); err != nil {
return fmt.Errorf("body %w", err)
}
return nil
}
func equals[T comparable](got, exp T) error {
if got != exp {
return fmt.Errorf("%v, expected %v", got, exp)
}
return nil
}
func contains(got string, expect ...string) error {
var miss []string
for _, exp := range expect {
if !strings.Contains(got, exp) {
miss = append(miss, exp)
}
}
if len(miss) > 0 {
return fmt.Errorf("missing %q", miss)
}
return nil
}