End-to-end tests
Send requests over the network to a running server with EnableNetworking.
By default apitest calls the handler in process. EnableNetworking sends the request over the network instead, so the same builders can test a server running locally, in a container or in a staging environment.
client := &http.Client{Timeout: 5 * time.Second}
apitest.New().
EnableNetworking(client).
Get(baseURL + "/health").
Expect(t).
Status(http.StatusOK).
End()- The URL must be absolute, including the scheme and host.
- Pass a client to control timeouts, TLS and redirects. Without one,
http.DefaultClientis used. - No handler is needed. A test without a handler and without networking fails.
Sessions
Each apitest test sends one request. A client with a cookie jar keeps cookies between tests, which models a browser session:
func TestLoginFlow(t *testing.T) {
srv := httptest.NewServer(newSessionApp())
defer srv.Close()
// the cookie jar carries the session cookie between requests
jar, _ := cookiejar.New(nil)
client := &http.Client{Jar: jar, Timeout: 5 * time.Second}
apitest.New().
EnableNetworking(client).
Post(srv.URL + "/login").
Expect(t).
Status(http.StatusNoContent).
CookiePresent("session").
End()
apitest.New().
EnableNetworking(client).
Get(srv.URL + "/me").
Expect(t).
Status(http.StatusOK).
Body(`{"name": "jon"}`).
End()
}
Mocks and networking
Mocks replace a transport inside the test process. They cannot answer calls made by a server running in another process, so end-to-end tests run against real dependencies or the test doubles of that environment.
Keep mocks and networking apart in the same test. Mocks replace the transport of http.DefaultClient, or of the client given to HttpClient, so when the networking client is one of those, the request to the server is matched against the mocks instead of being sent.
httptest.Server
httptest.NewServer starts a real server on a free local port, which is useful to test behaviour that only happens over a real connection, such as TLS, HTTP/2 or connection handling. Most tests do not need it, because calling the handler in process is faster and covers the application logic.