Go测试如何测试HTTP接口_Go接口测试方案解析

httptest 是 Go 测试 HTTP 接口最直接可靠的方式:内存中完成请求响应,不占端口不依赖网络;单元测试首选 httptest.NewRequest + httptest.NewRecorder,集成测试需用 httptest.NewServer。

httptest 是 Go 测试 HTTP 接口最直接、最可靠的方式——它不启动真实服务器,不占端口,也不依赖网络,所有请求响应都在内存中完成。

httptest.NewRequest + httptest.NewRecorder 测 handler 函数

这是 90% 的单元测试场景该选的方式:快、隔离、可控。

  • 构造请求:http.NewRequest("POST", "/api/users", strings.NewReader(`{"name":"alice"}`)),记得设 Content-Type: application/json
  • 捕获响应:w := httptest.NewRecorder(),它实现了 http.ResponseWriter,但只往内存写
  • 直接调用 handler:myHandler(w, req),不是发网络请求,而是函数调用
  • 断言时别只看状态码:w.Code == http.StatusCreated,更要检查 w.Header().Get("Content-Type")json.U

    nmarshal(w.Body.Bytes(), &resp)
    后字段值是否正确
  • 常见错误:忘了设置 req.Header.Set("Content-Type", ...),导致 handler 解析 body 失败;或用 w.Body.String() 做字符串匹配,而 JSON 字段顺序/空格/换行不固定,应优先解码后比对结构

httptest.NewServer 测客户端或集成行为

当你在测一个 *http.Client、SDK 封装、或需要重定向/Cookie/多次请求的逻辑时,必须用它。

  • 它会自动监听一个空闲端口,返回一个 *httptest.Server,其 URL 字段可直接传给 client
  • 务必 defer server.Close(),否则端口泄漏,连续跑测试会 panic
  • 不要硬编码 "http://localhost:8080",要用 server.URL + "/path"
  • 适合验证 client 是否设置了正确 header、是否处理了 401、是否重试了 503——这些行为只有真实 round-trip 才能触发
  • 性能开销略大(毕竟要走 TCP 栈模拟),所以仅用于“必须走 client 路径”的测试,别滥用

测带路径参数或查询参数的接口

Go 原生 http.ServeMux 不解析 /:id,路由库(如 gorilla/muxchi)才做这步。测试时得按实际解析方式准备请求。

  • 查询参数:直接拼进 URL,比如 http.NewRequest("GET", "/users?id=123&role=admin", nil),handler 中用 r.URL.Query().Get("id")
  • 路径参数:若用 gorilla/mux,需手动注入变量:mux.SetURLVars(req, map[string]string{"id": "789"})
  • 别指望 r.URL.Path 自动被“解析”成参数——那是路由层的事,handler 层看到的仍是原始路径字符串
  • 如果 handler 里混用了 r.URL.Query()r.URL.Path 提取逻辑,测试就得覆盖两种构造方式,否则漏掉边界 case

测试失败时最容易忽略的一点

很多测试只验证“返回了什么”,却没验证“不该发生什么”。比如 handler 本该调用一次数据库 Insert(),但测试没 mock、也没断言调用次数,结果逻辑出错也通过。

  • 把外部依赖(DB、缓存、第三方 client)抽成接口,测试时注入 mock 实现
  • 在 mock 方法里加计数器或记录调用参数,测试末尾 assert 调用次数和参数是否匹配
  • HTTP 层测试不是终点——状态码对、JSON 对,不代表业务逻辑对。真正的难点永远在“handler 内部是否按预期调用了依赖”