Go测试中应优先用t.Short()配合t.Skip跳过耗时测试,而非os.Getenv;集成测试用// +build integration隔离;禁用time.Sleep,改用mock和接口抽象。

用 -short 标记跳过耗时测试
Go 原生支持通过 -short 标记临时禁用耗时测试,Gin 单元测试可直接复用这套机制。关键不是“跳过”,而是让测试主动感知并提前返回——t.Short() 返回 true 时,就该立刻 t.Skip()。
常见错误是只加了 go test -short 却没在测试函数里检查,结果用例照常执行。
- 在耗时测试开头加
if t.Short() { t.Skip("skipping slow test in short mode") } - 适合场景:涉及真实 HTTP 请求、数据库连接、文件 I/O 或 sleep 的 handler 测试
- 注意:必须在
httptest.NewServer启动前判断,否则服务已起,跳过也晚了 - 不推荐用
os.Getenv自定义开关,破坏 Go 测试的统一行为
用 // +build !integration 条件编译隔离
当某些测试明显属于集成层(比如调用外部 API、连真实 MySQL),且你希望它们默认不参与 go test ./... 执行,可用构建标签隔离。
这类测试不应和纯单元测试混在一个文件里,否则覆盖率统计失真、CI 耗时不可控。
- 把耗时用例单独放在
handler_integration_test.go文件顶部加// +build integration - 运行普通单元测试:保持默认,不加任何 flag,这些文件自动被忽略
- 运行集成测试:显式启用
go test -tags=integration ./... - Gin handler 中若依赖
http.Client或database/sql,基本就该进 integration 分类
避免在 Gin handler 测试中误用 time.Sleep
有些开发者为“模拟延迟”在测试里写 time.Sleep(100 * time.Millisecond),这既非必要,又污染单元测试本质——handler 本身不 sleep,测试也不该 sleep。
真正需要测的是逻辑分支,而不是等待时间。sleep 只会让单测变慢、不稳定、难以并行。
- 要验证超时逻辑?mock
context.WithTimeout的返回值,而非真等 - 要验证重试行为?用
gomonkey打桩底层调用,控制返回次数 - 要测中间件限流?直接构造带
X-RateLimit-Limitheader 的请求,不启动 server - 所有对时间敏感的断言,都应基于注入的时钟接口(如
clock.Clock),而非系统时钟
复杂点在于测试边界模糊时的取舍
一个 Gin handler 是否“耗时”,不取决于它写了多少行,而取决于它是否触发了外部副作用:发 HTTP 请求、查 Redis、写日志到磁盘、调用 os/exec。这些行为一旦出现,就必须被 mock 或移到 integration 层。
最容易被忽略的是日志和监控埋点——哪怕只是调用 log.Printf 或 prometheus.Counter.Inc(),若未用 interface 抽象,也会让测试隐式依赖全局状态,导致无法稳定跳过。











