如何模拟http.Client Do方法

时间:2017-04-05 20:24:40

标签: unit-testing testing go mocking

我试图找到编写测试和模拟HTTP响应的解决方案。 在我接受界面的函数中:

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

我用base auth

制作http get请求
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)

我如何模拟这个HttpClient? 我正在寻找模拟库,例如:https://github.com/h2non/gock 但是只有模拟Get和Post

也许我应该以不同的方式做到这一点。 我很感激你的建议

4 个答案:

答案 0 :(得分:19)

任何具有与您的界面中的签名匹配的方法的结构都将实现该接口。例如,您可以创建结构ClientMock

type ClientMock struct {
}

使用方法

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

然后,您可以将此ClientMock结构注入GetOverview func。 Here是Go Playground的一个例子。

答案 1 :(得分:12)

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")

答案 2 :(得分:2)

您必须使用与接口匹配的方法创建结构。模拟通常用于测试目的,因此人们希望能够准备模拟方法的返回值。为此,我们使用与方法相对应的 func attributes 创建struct。

您的界面是:

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

等效模拟:

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
}

然后,下一步是编写一些测试。示例here

答案 3 :(得分:2)

我知道它已经有一段时间了,但我最近写了一些东西来帮助解决这个问题。

一般来说,为了模拟HTTP请求,我建议在本地启动一个真正的HTTP服务器,因为在Go中这很容易做到。 https://golang.org/pkg/net/http/httptest/是一种非常标准的方法(参见Server类型下给出的示例代码)。

然而,做了很多HTTP模拟,我想要更多的东西,比如一个好的模拟库:简单的期望设置,所有请求的验证等等。我通常使用https://godoc.org/github.com/stretchr/testify/mock用于嘲弄和想要的功能。

所以我写了https://github.com/dankinder/httpmock,基本上将两者结合起来。