Table-driven tests
Cover many scenarios with one test, and share configuration between tests.
Tables of scenarios
Each case in the table describes the dependencies and the expected response. t.Run gives every case its own name in the output:
func TestGetUser_Table(t *testing.T) {
tests := []struct {
name string
mocks []*apitest.Mock
wantStatus int
wantBody string
}{
{
name: "found",
mocks: []*apitest.Mock{getUserMock, getPreferencesMock},
wantStatus: http.StatusOK,
wantBody: `{"id": "1234", "name": "jon", "is_contactable": true}`,
},
{
name: "user not found",
mocks: []*apitest.Mock{
apitest.NewMock().
Get("http://users/api/user/1234").
RespondWith().
Status(http.StatusNotFound).
End(),
},
wantStatus: http.StatusNotFound,
wantBody: `{"error": "user not found"}`,
},
{
name: "preferences unavailable",
mocks: []*apitest.Mock{
getUserMock,
apitest.NewMock().
Get("http://preferences/api/preferences/1234").
RespondWith().
Status(http.StatusServiceUnavailable).
End(),
},
wantStatus: http.StatusBadGateway,
wantBody: `{"error": "upstream error"}`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
apitest.New(tt.name).
Mocks(tt.mocks...).
Handler(newUserAPI()).
Get("/user/1234").
Expect(t).
Status(tt.wantStatus).
Body(tt.wantBody).
End()
})
}
}
Passing the case name to apitest.New also names its sequence diagram, when reporting is on.
Parallel subtests and mocks
Mocks replace http.DefaultTransport for the whole process. Only call t.Parallel() in mocked subtests when each one uses its own client. See parallel tests.
Shared configuration
Every configuration method returns the *apitest.APITest, so a helper can set up the handler, mocks, reporting and anything else the tests have in common:
apiTest := func(name string) *apitest.APITest {
return apitest.New(name).
Handler(newUserAPI()).
Mocks(getUserMock, getPreferencesMock)
}
apiTest("gets a user").
Get("/user/1234").
Expect(t).
Status(http.StatusOK).
End()Tests then add only what is specific to them. A package level helper works the same way, as in reporting every test.