如何模拟返回JSON响应的http.Client

Geo*_*man 4 json unit-testing go

我正在尝试测试net/http用于发出请求的方法。具体来说,我要实现的目标是注入一个http.Client以某个JSON主体响应的模拟

type clientMock struct{}

func (c *clientMock) Do(req *http.Request) (*http.Response, error) {
  json := struct {
    AccessToken string `json:"access_token`
    Scope       string `json:"scope"`
  }{
    AccessToken: "123457678",
    Scope:       "read, write",
  }
  body := json.Marshal(json)
  res := &http.Response {
    StatusCode: http.StatusOK,
    Body:       // I haven't got a clue what to put here
  }
  return res
}

func TestRequest(t *testing.T) { //tests here }
Run Code Online (Sandbox Code Playgroud)

我确实知道的Body是类型io.ReadCloser接口。麻烦的是,我一生无法找到在模拟身体反应中实施该方法的方法。

示例如下发现这里至今只展示返回空白&http.Response{}

小智 6

In your test file (my_test.go):

type MyJSON struct {
        Id          string
        Age         int
}

// Interface which is the same as httpClient because it implements "Do" method.
type ClientMock struct {}

func (c *ClientMock) Do(req *http.Request) (*http.Response, error) {
    mockedRes := MyJSON {"1", 3}

    // Marshal a JSON-encoded version of mockedRes
    b, err := json.Marshal(mockedRes)
    if err != nil {
        log.Panic("Error reading a mockedRes from mocked client", err)
    }

    return &http.Response{Body: ioutil.NopCloser(bytes.NewBuffer(b))}, nil
}

// your test which will use the mocked response
func TestMyFunction(t *testing.T) {

    mock := &ClientMock{}
    actualResult := myFunction(mock)
    assert.NotEmpty(t, actualResult, "myFunction should have at least 1 result")

}
Run Code Online (Sandbox Code Playgroud)

In your implementation (main.go):

package main

import (
    "net/http"
)

func main() {
    myFunction(&http.Client{})
}
Run Code Online (Sandbox Code Playgroud)


Jim*_*imB 5

虽然使用来模拟整个请求周期可能更有用httptest.Server,但是您可以使用ioutil.NopCloser它在任何阅读器周围创​​建更紧密的联系:

Body: ioutil.NopCloser(bytes.NewReader(body))
Run Code Online (Sandbox Code Playgroud)

如果您想要一个空的正文,请提供没有内容的阅读器。

Body: ioutil.NopCloser(bytes.NewReader(nil))
Run Code Online (Sandbox Code Playgroud)