Test Web API
Learn how to write unit tests on a web API, how to mock HTTP requests, and how to record HTTP responses.
Go fits well for testing web APIs. Thanks to the http
package of the Go standard library, it is very easy to launch a web server and serve incoming requests. Whenever an HTTP request reaches our server, one handler is responsible for replying to it with the requested data. To get the data, each handler may call a database, a third-party system, and so on. However, to unit test our HTTP handlers, we don’t want to spin up an actual HTTP server.
The httptest
package
The httptest
package of the standard library provides us with everything we need to mock a request for our handlers. The interface that a handler has to implement is the following:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
The ResponseWriter
is an interface that contains all the methods used to construct the HTTP response. Conversely, the *Request
includes all the HTTP request details that the client provides to the server. It’s pretty hard and time-consuming to mock these two things out. That’s why the httptest
package provides the NewRequest
function and the ResponseRecorder
.
Mocking HTTP request
To mock out the HTTP request, we only need to call the NewRequest
function, which returns an instance of the *http.Request
type. The function’s signature is:
func NewRequest(method, target string, body io.Reader) *http.Request
It accepts the following arguments:
- The HTTP method
- The address of the resource to contact
- The request payload, if any
After we instantiate and set up the request, we can focus on the server side.
Recording the HTTP response
Again, in the httptest
package, we can take advantage of the capabilities provided by the ResponseRecorder
type. To instantiate it, we have to invoke the following function:
func NewRecorder() *ResponseRecorder
The *ResponseRecorder
is meant to be a drop-in replacement of a real HTTP server. As its name suggests, it records every HTTP response that might be asserted later by the test code. To get the actual *http.Response
, we’ve to invoke the Result()
method on an instance of the ResponseRecorder
struct. The signature of the Result()
method is as follows:
func (rw *ResponseRecorder) Result() *http.Response
When we retrieve an HTTP response, we’ll be able to assert its status code, the payload, the headers, and so on.
Ping Web API
Let’s start with a trivial example to understand how to unit test a basic handler. The web API is the ping/pong
one, we discussed in the previous lesson.
Get hands-on with 1200+ tech skills courses.