douduoquan2824
douduoquan2824
2017-04-05 20:24
浏览 219
已采纳

如何模拟http.Client Do方法

I'm trying to find a solution to write test and mock HTTP response. In my function where I accept interface:

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

I makes http get request with base auth

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'm looking for mock library, for instance: https://github.com/h2non/gock but there is only mock for Get and Post

Maybe I should do it in a different way. I'll be grateful for advice

图片转代码服务由CSDN问答提供 功能建议

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

 类型HttpClient接口{
 Do(req * http.Request)(* http.Response,error)
} 
    
 
 

我通过基本身份验证发出http获取请求

  func GetOverview(客户端HttpClient,概述*概述)(*概述,错误){
 
  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)
 res,err:= client.Do(request)
   
 
 

如何模拟此HttpClient? 我正在寻找模拟库,例如: https://github.com/h2non/gock ,但是只有Get and Post的模拟功能

也许我应该以其他方式进行 。 我会b 感谢您的建议

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • doubian6241
    doubian6241 2017-04-05 20:45
    已采纳

    Any struct with a method matching the signature you have in your interface will implement the interface. For example, you could create a struct ClientMock

    type ClientMock struct {
    }
    

    with the method

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

    You could then inject this ClientMock struct into your GetOverview func. Here's an example in the Go Playground.

    点赞 评论
  • dongxuying7583
    dongxuying7583 2017-04-06 03:31

    You have to create a struct with methods that match interface. Mocks are commonly used for testing purposes, therefore people want the ability to prepare return values of mock methods. To achieve this, we create struct with func attributes corresponding to methods.

    As your interface is:

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

    Equivalent mock:

    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, next step is to write some tests. Example here.

    点赞 评论
  • dongyu3712
    dongyu3712 2018-04-26 16:57

    I know it's been a little while but I just wrote something to help with this recently.

    Generally to mock HTTP requests I recommend starting up a real HTTP server locally, since in Go this is easy to do. https://golang.org/pkg/net/http/httptest/ is a pretty standard way to do that (see the example code given under the Server type).

    However having done a lot of HTTP mocking I wanted something that does a little more, like a good mock library would: easy setting of expectations, validation that all requests were made, etc. I have generally used https://godoc.org/github.com/stretchr/testify/mock for mocking and wanted features like that.

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

    点赞 评论
  • doulun0651
    doulun0651 2018-07-07 23:22

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

    // 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")
    
    点赞 评论

相关推荐