Go语言 如何模拟http.ClientDo方法

iovurdzv  于 2023-08-01  发布在  Go
关注(0)|答案(5)|浏览(105)

我试图找到一个解决方案来编写测试和模拟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的mock
也许我应该用不同的方式来做。我将感激你的忠告

00jrzges

00jrzges1#

任何具有与您界面中的签章相符之方法的结构,都会实作界面。例如,您可以创建一个结构ClientMock

type ClientMock struct {
}

字符串
该方法

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


然后可以将此ClientMock结构体注入GetOverview函数。Here是围棋赛场上的一个例子。

pcww981p

pcww981p2#

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

字符串

sq1bmfud

sq1bmfud3#

你必须创建一个方法与接口匹配的结构体。模拟通常用于测试目的,因此人们希望能够准备模拟方法的返回值。为了实现这一点,我们创建了对应于方法的带有 *func属性 * 的结构体。
因为你的界面是:

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

9fkzdhlc

9fkzdhlc4#

我知道这是一个小的一段时间,但我只是写了一些东西,以帮助这最近。
一般来说,为了模拟HTTP请求,我建议在本地启动一个真实的的HTTP服务器,因为在Go中这很容易做到。https://golang.org/pkg/net/http/httptest/是一种非常标准的方法(请参阅Server类型下给出的示例代码)。
然而,在做了很多HTTP mocking之后,我想要做得更多一点的东西,就像一个好的mock库一样:容易设定期望值,验证所有请求都已提出等。我通常使用https://godoc.org/github.com/stretchr/testify/mock进行模拟,并希望具有这样的功能。
所以我写了https://github.com/dankinder/httpmock,它基本上结合了两者。

h9vpoimq

h9vpoimq5#

如果您使用的是http库中的Client,我更喜欢使用RoundTripper来完成此操作。
应首先定义RoundTripper

type mockRoundTripper struct {
    response *http.Response
}

func (rt *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
    return rt.response, nil
}

字符串
你的unittest测试看起来像这样:

func TestGetOverview(t *testing.T) {
    // Set up your response
    json := `{"code": 0, "message": "success"}`
    recorder := httptest.NewRecorder()
    recorder.Header().Add("Content-Type", "application/json")
    recorder.WriteString(json)
    expectedResponse := recorder.Result()

    // Create an HTTP client
    client := http.Client{Transport: &mockRoundTripper{expectedResponse}}

    // Call your function
    overview, err := yourlib.GetOverview(client, &yourlib.Overview{})
    ....
}


下面是一个简单的例子:https://go.dev/play/p/wtamTRahsZX

相关问题