This library builds on Go's built-in httptest library, adding a more
mockable interface that can be used easily with other mocking tools like
testify/mock. It does this by providing a Handler that receives
HTTP components as separate arguments rather than a single *http.Request
object.
Where the typical http.Handler interface is:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
This library provides a server with the following interface, which works naturally with mocking libraries:
// Handler is the interface used by httpmock instead of http.Handler so that it can be mocked very easily.
type Handler interface {
Handle(method, path string, body []byte) Response
}
The most primitive example, the OKHandler
, just returns 200 OK
to everything.
s := httpmock.NewServer(&httpmock.OKHandler{})
defer s.Close()
// Make any requests you want to s.URL(), using it as the mock downstream server
This example uses MockHandler, a Handler that is a testify/mock object.
downstream := httpmock.NewMockHandler(t)
// A simple GET that returns some pre-canned content
downstream.On("Handle", "GET", "/object/12345", mock.Anything).Return(httpmock.Response{
Body: []byte(`{"status": "ok"}`),
})
s := httpmock.NewServer(downstream)
defer s.Close()
//
// Make any requests you want to s.URL(), using it as the mock downstream server
//
downstream.AssertExpectations(t)
If instead you wish to match against headers as well, a slightly different httpmock object can be used (please note the change in function name to be matched against):
downstream := &httpmock.NewMockHandlerWithHeaders(t)
// A simple GET that returns some pre-canned content and expects a specific header.
// Use MultiHeaderMatcher for multiple headers.
downstream.On("HandleWithHeaders", "GET", "/object/12345", HeaderMatcher("MOCK", "this"), mock.Anything).Return(httpmock.Response{
Body: []byte(`{"status": "ok"}`),
})
// ... same as above
The httpmock package also provides helpers for checking calls using json objects, like so:
// This tests a hypothetical "echo" endpoint, which returns the body we pass to it.
type Obj struct {
A string `json:"a"`
}
o := &Obj{A: "aye"}
// JSONMatcher ensures that this mock is triggered only when the HTTP body, when deserialized, matches the given
// object. Here, this mock response will get triggered only if `{"a":"aye"}` is sent.
downstream.On("Handle", "POST", "/echo", httpmock.JSONMatcher(o)).Return(httpmock.Response{
Body: httpmock.ToJSON(o),
})