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

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

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

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

字符串
我用base auth发出http get请求

  1. func GetOverview(client HttpClient, overview *Overview) (*Overview, error) {
  2. request, err := http.NewRequest("GET", fmt.Sprintf("%s:%s/api/overview", overview.Config.Url, overview.Config.Port), nil)
  3. if (err != nil) {
  4. log.Println(err)
  5. }
  6. request.SetBasicAuth(overview.Config.User, overview.Config.Password)
  7. resp, err := client.Do(request)


我怎么能嘲笑这个HttpClient?我正在寻找模拟库,例如:https://github.com/h2non/gock但只有Get和Post的mock
也许我应该用不同的方式来做。我将感激你的忠告

00jrzges

00jrzges1#

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

  1. type ClientMock struct {
  2. }

字符串
该方法

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


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

pcww981p

pcww981p2#

net/http/httptest软件包是您最好的朋友:

  1. // generate a test server so we can capture and inspect the request
  2. testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
  3. res.WriteHeader(scenario.expectedRespStatus)
  4. res.Write([]byte("body"))
  5. }))
  6. defer func() { testServer.Close() }()
  7. req, err := http.NewRequest(http.MethodGet, testServer.URL, nil)
  8. assert.NoError(t, err)
  9. res, err := http.DefaultClient.Do(req)
  10. assert.NoError(t, err)
  11. assert.Equal(t, scenario.expectedRespStatus, res.StatusCode, "status code should match the expected response")

字符串

sq1bmfud

sq1bmfud3#

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

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

字符串
等效模拟:

  1. type MockClient struct {
  2. DoFunc func(req *http.Request) (*http.Response, error)
  3. }
  4. func (m *MockClient) Do(req *http.Request) (*http.Response, error) {
  5. if m.DoFunc != nil {
  6. return m.DoFunc(req)
  7. }
  8. return &http.Response{}, nil
  9. }


下一步是编写一些测试。示例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

  1. type mockRoundTripper struct {
  2. response *http.Response
  3. }
  4. func (rt *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
  5. return rt.response, nil
  6. }

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

  1. func TestGetOverview(t *testing.T) {
  2. // Set up your response
  3. json := `{"code": 0, "message": "success"}`
  4. recorder := httptest.NewRecorder()
  5. recorder.Header().Add("Content-Type", "application/json")
  6. recorder.WriteString(json)
  7. expectedResponse := recorder.Result()
  8. // Create an HTTP client
  9. client := http.Client{Transport: &mockRoundTripper{expectedResponse}}
  10. // Call your function
  11. overview, err := yourlib.GetOverview(client, &yourlib.Overview{})
  12. ....
  13. }


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

展开查看全部

相关问题