首页 > 解决方案 > 如何模拟 http.NewRequest 以返回错误

问题描述

我有一个 Go 方法,它向外部网页发出 http 请求,我正在屏幕抓取。当一切按计划工作时,我进行了单元测试。我可以模拟 httpclient 并将响应设置为预定义的值。但是,当事情不起作用时,我无法创建测试。我想模拟 http.NewRequest 以返回错误。

我正在使用 httptest 和 go 工具封面。

测试方法:

func (cli *Client) GetSomething(sometext string) (string, error) {

    searchURL := strings.Replace(someUrl, "{PERSON_NAME}", url.QueryEscape(sometext), 1)
    req, err := http.NewRequest("GET", someUrl, nil)
    if err != nil {
    // I want to test this scenario
        return "", errors.Wrap(err, "failed to build request")
    }

    resp, err := cli.HTTPClient.Do(req)

    if err != nil {
        return "", errors.Wrap(err, "request failed")
    }

    defer resp.Body.Close()

    document, err := goquery.NewDocumentFromReader(resp.Body)

    if err != nil {
        return "", err
    }

    value:= document.Find(".someclass").Text()

    return value, nil
}

测试方法适用于 httpclient。不确定如何模拟 http.NewRequest 以返回错误。这可能永远不会发生,但只是为了完成并作为练习。

func TestGetSomethingFailedReqest(t *testing.T) {

    h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        panic("Create error")
    })

//TestingHTTPClient is a helper function to create an HTTPClient.  Not needed for this test.

    httpClient, teardown := test.TestingHTTPClient(h)  
    defer teardown()
    scraperClient := NewClient()
    scraperClient.HTTPClient = httpClient

    var person= "John Doe"

    _, err := scraperClient.GetSomething(person)

    assert.Regexp(t, ".*failed to build request", err.Error())
}

标签: unit-testinghttpgo

解决方案


如果你希望你的测试是可靠的,你应该尽量避免模拟。

因此,如果您想知道如何测试创建 http 请求的库,最好的方法是在单元测试中创建本地服务器,这样您就可以测试请求的各个方面。

我可以为您提供的最佳示例是:https ://github.com/gojek/heimdall/blob/master/httpclient/client_test.go 在 Heimdall 一个开源 http 客户端中,您可以看到他们如何在没有模拟的情况下实现测试。

对于您的具体问题,BentCoder 回复您:“只需使用“*?”作为请求方法。这应该返回net/http: invalid method "*?" error.


推荐阅读