Go测试网络错误需用MockHTTPClient模拟异常,如超时、连接拒绝、5xx状态码、空body、JSON解析失败等,通过自定义RoundTripper或httptest.Server精确控制响应,并断言具体错误类型确保覆盖边界。
在 Go 中测试网络请求的错误处理,关键在于绕过真实 HTTP 客户端,用 http.Client 的 Transport 字段或直接替换 http.DefaultClient,注入可控的异常响应(如超时、连接拒绝、5xx 状态码、空 body、JSON 解析失败等)。不需要启动真实服务,也不依赖外部环境。
实现 http.RoundTripper 接口,可精确控制每次请求的行为。适合模拟:连接超时、TLS 握手失败、无响应、返回非 2xx 状态码、body 读取中断等。
net.ErrClosed 或自定义 error 模拟连接被拒或中断time.AfterFunc 延迟 panic 或关闭 response.Body 模拟读取超时&http.Response{StatusCode: 503, Body: io.NopCloser(strings.NewReader(""))} 返回服务不可用Body 是一个在 Read() 时返回 io.EOF 或 io.ErrUnexpectedEOF 的 mock reader,触发 JSON 解析失败httptest.NewUnstartedServer 创建服务后不调用 .Start(),再用普通 client 请求它,会立即返回 dial tcp [::1]:xxxx: connect: connection refused —— 这是最贴近真实“服务未启动”的场景。
srv.Close(),再发请求,复现“连接已关闭”panic 或 return,让 response 不完整,触发客户端解析异常time.Sleep(3 * time.Second) 配合 client 设置 Timeout: 1 * time.Second,精准触发超时避免每个测试都重写 RoundTripper,可定义结构体如:
type MockHTTPClient struct {
StatusCode int
Body string
Err error
Delay time.Duration
}它的 RoundTrip(*http.Request) (*http.Response, error) 方法根据字段返回对应结果。测试中只需:
client := &http.Client{
Transport: &MockHTTPClient{StatusCode: 500, Body: `{"error":"server"}`},
}
// 注入到被测对象(如 service.DoReq
uest(...))
不要只检查 err != nil,要断言错误类型和内容:
errors.Is(err, context.DeadlineExceeded) 区分超时与其它错误json.Unmarshal 失败,检查 errors.As(err, &json.SyntaxError{})
net.OpError,用 errors.Is(err, syscall.ECONNREFUSED) 或 errors.Is(err, context.Canceled)
fmt.Errorf("fetch user: %w", err))没吞掉底层关键信息