go test默认只运行当前包的Test函数,测试文件须为_test.go、与被测代码同包同目录、函数名以Test开头且接收testing.T参数;集成测试需用//go:build integration标签和-tags=integration显式启用。

go test 默认只跑单元测试,集成测试必须显式控制——不加隔离,一跑就崩。
Test函数命名和_test.go文件位置怎么定
Go 不靠目录或框架识别测试,只认文件名和函数签名:_test.go 文件 + TestXxx 函数(首字母大写)才会被 go test 扫到。它必须和被测代码在同一个包里(同目录、同 package 声明),否则无法访问未导出字段或函数。
常见错误是把测试文件放错目录,比如:
- 想测
internal/service/user.go,却把user_test.go放在cmd/下 → 包不一致,go test找不到,或报undefined: CreateUser - 测试文件用了
package main,但被测代码是package service→ 编译失败
正确做法:测试文件和源文件严格同目录、同包名,哪怕只是测一个私有 helper 函数。
如何让集成测试不干扰日常开发
集成测试要连 DB、HTTP、Redis,CI 里没这些依赖,本地也未必开全。硬跑等于等超时或 panic。
立即学习“go语言免费学习笔记(深入)”;
必须用两层防护:
- 文件命名:集成测试文件用
_integration_test.go后缀(如user_integration_test.go),不是强制规则,但能一眼区分 - 运行时守卫:每个集成测试开头加
if testing.Short() { t.Skip("skipping integration test") },再加依赖探活(比如db.Ping()失败就t.Skipf)
这样你日常用 go test -short ./... 就只跑单元测试;手动验证时才用 go test ./... -run Integration 或去掉 -short。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
mock 和 real 依赖切换为什么总失效
根本原因:测试里还在 new 真实 client,或者依赖藏在全局变量里。
真正可控的切换方式只有两种:
- 接口注入:把
*sql.DB换成DBExecutor接口,测试传mockDB,生产传realDB - 构造函数参数化:service 初始化时把 HTTP client、DB、cache 全部作为参数传入,测试塞 mock,main 函数里才 new 真的
绝对不要碰 init()、全局单例、包级变量初始化的 client——它们会让测试之间互相污染,t.Cleanup 都救不回来。
go test -race 跑集成测试会出什么问题
会炸,而且很典型:集成测试常启 goroutine、共享数据库连接池、复用 HTTP transport,-race 一开就报 data race。
这不是 bug,是预期行为。解决方案很直接:
- 单元测试可以放心开
-race,它轻量、隔离、无副作用 - 集成测试默认禁用
-race,CI 脚本里明确写成go test -short ./... -race(不含集成) - 真要查 race?单独跑某个集成测试,不加
-race,先确保逻辑通;再用go run -race单步调试关键路径
最易被忽略的是:哪怕你写了 t.Skip(),只要测试函数被 go test 扫到,它仍会参与 -race 检查——所以文件名后缀和 testing.Short() 必须同时存在,缺一不可。

















