为超时的单元测试创​​建 deadlineExceededError:true

我正在尝试在我的项目中创建一个单元测试,我在其中模拟 http 客户端并设置客户端必须返回的响应。我需要这样的行为,因为如果 http 客户端因超时而失败,我的代码需要相应的行为:因此我需要模拟 http 客户端以返回 deadlineExceededError 并对其进行单元测试。


到目前为止我尝试的是以client.Do返回的方式模拟客户端 Do 函数:


GetDoFunc = func(*http.Request) (*http.Response, error) {

    return nil, &url.Error{

        Op:  "Post",

        Err: context.DeadlineExceeded,

    }

}

它有效但不完全,这意味着当我以这种模拟行为执行代码时,返回的错误类型是:


error(*net/url.Error) *{Op: "Post", URL: "", Err: error(context.deadlineExceededError) {}}

这又是正确的,但不完全正确。为什么?因为如果我运行代码并且发生真正的超时,我会得到更完整的东西:


error(*net/url.Error) *{Op: "Post", URL: "http://localhost:4500/scan/", Err: error(*net/http.httpError) *{err: "context deadline exceeded (Client.Timeout exceeded while awaiting headers)", timeout: true}}

我最感兴趣的是timeout: true。如果我设法告诉我的模拟返回它,我可以断言,我发现它比仅断言返回的错误是deadlineExceededError类型更完整。


慕村225694
浏览 104回答 1
1回答

繁星淼淼

为了不让测试过于复杂,我建议您采用这种方法。首先,首先定义您的错误:type timeoutError struct {    err     string    timeout bool}func (e *timeoutError) Error() string {    return e.err}func (e *timeoutError) Timeout() bool {    return e.timeout}这样,timeoutError同时实现了Error()和Timeout接口。然后你必须为 HTTP 客户端定义模拟:type mockClient struct{}func (m *mockClient) Do(req *http.Request) (*http.Response, error) {    return nil, &timeoutError{        err:     "context deadline exceeded (Client.Timeout exceeded while awaiting headers)",        timeout: true,    }}这只是返回上面定义的错误并nil作为 http.Response。最后,让我们看看如何编写示例单元测试:func TestSlowServer(t *testing.T) {    r := httptest.NewRequest(http.MethodGet, "http://example.com", nil)    client := &mockClient{}    _, err := client.Do(r)    fmt.Println(err.Error())}如果您调试此测试并在变量上使用调试器暂停err,您将看到想要的结果。由于这种方法,您可以在不增加任何额外复杂性的情况下实现所需的功能。让我知道是否适合你!
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go