Go测试HTTP客户端应优先拦截传输层而非真实发请求,推荐用httptest.Server伪造服务端验证请求构造与响应处理,或用httpmock模拟多场景响应,也可手动替换Client.Transport实现轻量控制。
在 Go 中测试 HTTP 客户端,关键不是真的发请求,而是替换掉默认的 http.Client 的传输层(Transport),用 httpmock 或标准库的 httptest.Server 拦截并返回预设响应。
适合验证客户端逻辑是否正确构造请求、处理状态码和 JSON 响应等,不依赖第三方库。
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")
}
}
当你要覆盖多种响应场景(如 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")
}
}
如果你只想最小化依赖,可直接给 http.Client 设置自定义 Transport,实现 RoundTrip 方法。
http.RoundTripper 接口的结构体RoundTrip 里检查 *http.Request,按需返回 *http.Response
Body(比如用 io.NopCloser(strings.NewReader(...)))适用场景:学习原理、极简环境、或需要深度控制底层行为。
真实调用中,网络失败、JSON 解析失败、HTTP 状态码非 2xx 都很常见。测试时要覆盖:
httpmock.RegisterResponder 返回空
body 或超长 bodyTimeout,再用慢响应验证超时逻辑不复杂但容易忽略。