One minute
Mocking Native Http Go Client
How to cleanly mock Go's native net/http client in unit and integration tests using custom RoundTripper implementations.
If we have some Go code using http.Client we might want to unit test it.
To do so we can create a new custom interface:
type Client interface {
Do(req *http.Request) (*http.Response, error)
}
Having this new interface we can easily prepare a mock, in this example I’ll use testify:
type HTTPClientMock struct {
mock.Mock
}
Then we declare the method we want to mock, in our case Do:
func (m *HTTPClientMock) Do(req *http.Request) (*http.Response, error) {
args := m.Called(req)
return args[0].(*http.Response), args.Error(1)
}
Then in our test we just have to create a new instance of that mock:
clientMock := new(HTTPClientMock)
We can use that mock to inject it to any service that requires http.Client, and then with the following code we can set the expectation we want:
m.
On("Do", mock.MatchedBy(func(receivedReq *http.Request) bool {
assert.EqualValues(t, req.Method, receivedReq.Method, "invalid method")
assert.EqualValues(t, req.URL, receivedReq.URL, "invalid URL")
assert.EqualValues(t, req.Header, receivedReq.Header, "invalid header")
if "" == requestBody {
// if body is empty
assert.EqualValues(t, req.Body, receivedReq.Body, "invalid body")
} else {
// if we got some content
var err error
buf1 := new(bytes.Buffer)
_, err = buf1.ReadFrom(req.Body)
assert.NoError(t, err)
buf2 := new(bytes.Buffer)
_, err = buf2.ReadFrom(receivedReq.Body)
assert.NoError(t, err)
assert.JSONEq(t, buf1.String(), buf2.String(), "invalid JSON body")
}
return true
})).
Once().
Return(res, nil)