模拟一个外部库对象以在go中进行测试

6gpjuf90  于 2023-10-14  发布在  Go
关注(0)|答案(1)|浏览(100)

我正在尝试对一个做post的golang HTTP函数进行单元测试。要做到这一点而不实际发布到API,我想从net/http包的*http.Client对象中模拟Post()方法。挑战在于,据我所知,我不能创建一个Mock对象并将其粘贴到外部库对象上,我想知道这是否可能。以下是我的测试:
http_test.go

type (
    MockPost struct {
        mock.Mock
    }
)

func (m *MockPost) Post(url string, contentType string, body io.Reader) (resp *http.Response, err error) {
    args := m.Called(url, contentType, body)
    return nil, args.Error(0)
}

func TestFunc(t *testing.T) {
    mockPost := &MockPost{}
    mockPost.On("Post", "apistring", nil, mock.Anything).Return(nil)

    err := functionNeedsTesting("apistring", nil, *mockPost) // <- cannot use mockPost bc expected *http.Client yada yada...
    if err != nil {
        t.Error(err)
        t.FailNow()
    }
    mockPost.AssertExpectations(t)
}

下面是我想测试的简化函数,这里client使用*http.Client,我可以模拟它吗?
http.go

func makePost(apiString string, body []byte, client *http.Client) error {
    resp, err := client.Post(apiString, "application/json", bytes.NewBuffer(body))
    if err != nil {
        return err
    }

    if resp.StatusCode != 201 { // created response code
        bodyBytes, err := io.ReadAll(resp.Body)
        if err != nil {
            return err
        }
        return fmt.Errorf("%s", bodyBytes)
    }
    return nil
}

以下是正确的错误:

cannot use *mockPost (variable of type MockPost) as *http.Client value in argument to makePost
aiazj4mn

aiazj4mn1#

你想要做的是让makePost接受一个接口,而不是http.Client

type HttpPoster interface {
    Post(url, contentType string, body io.Reader) (resp *http.Response, err error)
}

func makePost(apiString string, body []byte, client HttpPoster) error {
    resp, err := client.Post(apiString, "application/json", bytes.NewBuffer(body))
    if err != nil {
        return err
    }

    if resp.StatusCode != 201 { // created response code
        bodyBytes, err := io.ReadAll(resp.Body)
        if err != nil {
            return err
        }
        return fmt.Errorf("%s", bodyBytes)
    }
    return nil
}

然后你就可以通过模拟考试了

相关问题