如何在Golang中测试HTTP客户端_模拟外部API请求响应

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,再用慢响应验证超时逻辑

不复杂但容易忽略。