How to trick the http.Client Do method

I am trying to find a solution to write a test and simulate an HTTP response. In my function where I accept the interface:

type HttpClient interface {
    Do(req *http.Request) (*http.Response, error)
}

      

I am doing http get request with basic authentication

func GetOverview(client HttpClient, overview *Overview) (*Overview, error) {

    request, err := http.NewRequest("GET", fmt.Sprintf("%s:%s/api/overview", overview.Config.Url, overview.Config.Port), nil)
    if (err != nil) {
        log.Println(err)
    }
    request.SetBasicAuth(overview.Config.User, overview.Config.Password)
    resp, err := client.Do(request)

      

How can I mock this HttpClient? I am looking for a mock library like: https://github.com/h2non/gock but there is only mock for Get and Post

Maybe I should do it differently. I would be grateful for the advice

+18


source to share


5 answers


Any structure with a method that matches the signature you have on your interface will implement the interface. For example, you can create a structClientMock

type ClientMock struct {
}

      

using the method



func (c *ClientMock) Do(req *http.Request) (*http.Response, error) {
    return &http.Response{}, nil
}

      

Then you can insert this structure ClientMock

into your GetOverview

func. Here's an example on the Go Playground.

+21


source


The package is your best friend: net/http/httptest



// generate a test server so we can capture and inspect the request
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
    res.WriteHeader(scenario.expectedRespStatus)
    res.Write([]byte("body"))
}))
defer func() { testServer.Close() }()

req, err := http.NewRequest(http.MethodGet, testServer.URL, nil)
assert.NoError(t, err)

res, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, scenario.expectedRespStatus, res.StatusCode, "status code should match the expected response")

      

+14


source


I know there has been little, but I just wrote something to help with this lately.

Generally, for mocking HTTP requests, I recommend running a real HTTP server locally as this is easy to do in Go. https://golang.org/pkg/net/http/httptest/ is a pretty standard way to do this (see the sample code given in the server type).

However, after doing a lot of HTTP mocking, I wanted something more like a good mock library: easy setting of expectations, checking that all requests were made, etc. I used to usually use https://godoc.org/github.com/stretchr/testify/mock for mockery and desired features.

So, I wrote https://github.com/dankinder/httpmock which basically combines the two.

+3


source


You need to create a structure with methods that match the interface. Max is usually used for testing purposes, so people want ready-made return values ​​of mock methods. To do this, we create a structure with func attributes corresponding to the methods.

As your interface:

type HttpClient interface {
    Do(req *http.Request) (*http.Response, error)
}

      

Equivalent layout:

type MockClient struct {
    DoFunc func(req *http.Request) (*http.Response, error)
}

func (m *MockClient) Do(req *http.Request) (*http.Response, error) {
    if m.DoFunc != nil {
        return m.DoFunc(req)
    }
    return &http.Response{}, nil
}

      

Then, the next step is to write some tests. An example is here .

+2


source


Create a dummy server from httpclient. Working example here:

https://github.com/mohammadiliyash/golang-mock-http-call

0


source







All Articles