httptest.Server 是最轻量可靠的无网络测试方案,不走 TCP、启动快、需传入自定义 client;httpmock 适合不可改代码但易因自定义 Transport 失效;自定义 RoundTripper 最可控,须注意 Body、StatusCode、重定向、Header 和 Cookie 的完整模拟。

用 httptest.Server 替代真实服务调用
Go 标准库的 httptest.Server 是最轻量、最可靠的无网络测试方案——它不走 TCP,不依赖本地端口占用或防火墙设置,启动快、销毁干净。只要被测代码接受 *http.Client 或能传入自定义 http.RoundTripper,就能彻底隔离外部依赖。
常见错误是硬编码 http.DefaultClient 或直接调用 http.Get,导致无法注入 mock 传输层。必须把 client 提取为可配置参数,哪怕只是加个 client *http.Client 字段到结构体里。
- 使用场景:测试调用第三方 API 的封装函数(如
FetchUserInfo)、HTTP 客户端 SDK、微服务间调用逻辑 - 关键点:启动
httptest.NewServer后,用其URL替换原请求地址;测试结束务必调用server.Close() - 注意
httptest.Server默认监听127.0.0.1,若代码校验 Host 头或做 Referer 检查,需手动设置req.Host或在 handler 中透传
用 httpmock 拦截特定域名请求(适合已有不可改代码)
当没法改被测代码(比如闭源 SDK、遗留项目),httpmock 是唯一可行的“无侵入”方案。它通过替换 http.DefaultTransport 实现请求拦截,对调用方完全透明。
但要注意:它只生效于未显式指定 Transport 的 client;一旦代码用了自定义 http.Transport,httpmock 就失效,且不会报错,只会默默走真实网络——这是最常踩的坑。
立即学习“go语言免费学习笔记(深入)”;
- 初始化必须在测试开始前调用
httpmock.Activate(),结束时httpmock.DeactivateAndReset() - 匹配规则优先用
httpmock.RegisterResponder+httpmock.GET等方法,避免用模糊的httpmock.RegisterResponder("GET", "https://api.example.com/*", ...),路径通配可能漏匹配 - 返回 JSON 响应时,别直接写字符串,用
httpmock.NewStringResponder(200, `{"id":1}`),否则 Content-Type 缺失,被测代码可能解析失败
RoundTripper 自定义实现比 mock 更可控
比起第三方库,自己实现一个 http.RoundTripper 接口更简单、更稳定,也更容易调试。它本质就是一个函数:输入 *http.Request,输出 *http.Response 或 error。
优势在于完全掌控响应时机和内容——比如模拟超时(time.Sleep(3 * time.Second))、随机失败、或根据请求 query 参数返回不同 body。没有魔法,不依赖全局状态,测试间零干扰。
- 典型结构:用
map[string]string存预设响应,key 是请求 URL(或 path),value 是 JSON 字符串;handler 中查表返回 - 注意
*http.Response的Body必须是io.ReadCloser,别直接赋值字符串,要用io.NopCloser(strings.NewReader(body)) - 如果被测代码检查
Response.StatusCode后续逻辑,记得在 mock response 中显式设好StatusCode字段,否则默认是 0
别忽略重定向、Header 和 Cookie 的 mock 行为
真实 HTTP 调用中,302 重定向、Authorization Header、Set-Cookie 响应头这些行为,往往在测试里被静默跳过。而 httptest.Server 默认不处理重定向,httpmock 默认也不携带 Cookie。
结果就是:测试通过了,但线上遇到 302 就 panic,或者没带 token 导致 401 —— 这类问题很难复现,因为本地环境通常没开重定向或鉴权。
- 若被测逻辑含重定向,测试 client 需设
CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse } - 需要验证请求 Header 是否正确?在
httptest.Server的 handler 里打印req.Header,或用httpmock的httpmock.GetRegisteredMatchers()查看是否命中 - Cookie 相关逻辑必须显式构造
http.Cookie并写入Response.Header,标准库不会自动帮你解析或回传
真正难的不是 mock 本身,而是把「哪些网络行为会影响业务逻辑」想全。一次请求里,Status Code、Header、Body、重定向、超时、TLS 错误、DNS 失败……每个都可能成为分支条件。漏掉任意一个,测试就只是看起来绿而已。










