Go测试HTTP客户端应优先拦截传输层而非真实发请求,推荐用httptest.Server伪造服务端验证请求构造与响应处理,或用httpmock模拟多场景响应,也可手动替换Client.Transport实现轻量控制。

在 Go 中测试 HTTP 客户端,关键不是真的发请求,而是替换掉默认的 http.Client 的传输层(Transport),用 httpmock 或标准库的 httptest.Server 拦截并返回预设响应。
用 httptest.Server 伪造服务端(推荐用于集成/端到端风格)
适合验证客户端逻辑是否正确构造请求、处理状态码和 JSON 响应等,不依赖第三方库。
- 启动一个临时 HTTP 服务,返回你想要的响应体、状态码、Header
- 把客户端的 BaseURL 指向这个本地 server.URL
- 测试完记得调用
server.Close()
示例:
func TestMyClient_GetUser(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" || r.URL.Path != "/users/123" {
t.Fatal("unexpected request")
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{"id": 123, "name": "Alice"})
}))
defer server.Close()
client := NewAPIClient(server.URL) // 把 server.URL 当作 API 地址传入
user, err := client.GetUser(context.Background(), "123")
if err != nil {
t.Fatal(err)
}
if user.Name != "Alice" {
t.Error("expected Alice")
}
}
用 httpmock 模拟特定请求(适合单元测试、更轻量)
当你要覆盖多种响应场景(如 404、超时、网络错误)且不想启 HTTP 服务时,httpmock 更灵活。
立即学习“go语言免费学习笔记(深入)”;
- 导入
github.com/jarcoal/httpmock - 在测试开始前调用
httpmock.Activate(),结束时DeactivateAndReset() - 用
httpmock.RegisterResponder()匹配方法 + URL,返回自定义响应
示例:
func TestMyClient_GetUser_WithHttpMock(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpmock.RegisterResponder("GET", "https://api.example.com/users/456",
httpmock.NewStringResponder(200, `{"id":456,"name":"Bob"}`))
client := NewAPIClient("https://api.example.com")
user, err := client.GetUser(context.Background(), "456")
if err != nil {
t.Fatal(err)
}
if user.Name != "Bob" {
t.Error("expected Bob")
}
}
替换 Client.Transport 手动拦截(纯标准库,无依赖)
如果你只想最小化依赖,可直接给 http.Client 设置自定义 Transport,实现 RoundTrip 方法。
- 写一个满足
http.RoundTripper接口的结构体 - 在
RoundTrip里检查*http.Request,按需返回*http.Response - 注意:要手动构造
Body(比如用io.NopCloser(strings.NewReader(...)))
适用场景:学习原理、极简环境、或需要深度控制底层行为。
别忘了测试错误路径
真实调用中,网络失败、JSON 解析失败、HTTP 状态码非 2xx 都很常见。测试时要覆盖:
- 模拟 500 响应,检查是否返回 error
- 返回非法 JSON,验证解码是否出错
- 用
httpmock.RegisterResponder返回空 body 或超长 body - 对 client 设置
Timeout,再用慢响应验证超时逻辑
不复杂但容易忽略。










