测试代码和生产依赖必须物理隔离,不能写入go.mod;mock实现须置于_test.go文件中;集成测试依赖需用// +build integration标签隔离。

测试代码和生产依赖必须物理隔离,不能靠注释或条件编译“假装分开”——Go 的 go mod 不区分 test 与 prod 依赖,所有 require 都参与构建,test-only 包混进 go.sum 会导致构建不可重现、CI 失败、甚至意外升级生产依赖。
test-only 依赖不能写进 go.mod
Go 没有 “devDependency” 概念。一旦你在 go.mod 里 require github.com/stretchr/testify v1.12.2,它就会出现在 go.sum 中,并被 go build 和 go test 一并解析——哪怕你只在 *_test.go 文件里 import 它。
- 正确做法:所有仅用于测试的包(如
github.com/stretchr/testify、github.com/golang/mock、github.com/matryer/is)**不显式写入go.mod**,而是靠go test自动拉取 - 验证方式:运行
go list -m all | grep testify,如果返回结果,说明它已被go mod记录;此时应删掉go.mod中对应行,再执行go mod tidy - 陷阱:用
go get -t或go install时可能悄悄写入go.mod,务必检查并清理
mock 实现必须放在 *_test.go 文件里
mock 结构体如果定义在普通 .go 文件中(比如 mock_user.go),它会被 go build 编译进最终二进制,即使没被生产代码引用——Go 不做死代码消除,只要文件被包含,就参与构建。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 安全位置:所有 mock 类型、fake 实现、testutil 工具函数,**必须放在
*_test.go文件中**(例如user_service_test.go或mocks_test.go) - 例外情况:若多个测试文件共用 mock,可新建
testmocks_test.go,但命名后缀仍为_test.go,且不能被非测试代码 import - 危险信号:如果
go list -f '{{.Name}}' ./...输出里出现 mock 类型名(如MockUserRepo),说明它已暴露给非测试包,需重构
集成测试依赖要显式跳过 CI 构建
集成测试常需 github.com/DATA-DOG/go-sqlmock 或 github.com/elazarl/goproxy 等包,它们不该出现在生产构建路径里。但若测试文件用了这些包,go build ./... 会失败——因为 go build 会扫描所有 .go 文件,包括 *_test.go,然后尝试解析其 import。
立即学习“go语言免费学习笔记(深入)”;
- 解决方案:对含敏感依赖的测试文件,顶部加
// +build integration,并在go test时用-tags=integration显式启用 - 同时确保:CI 脚本用
go build ./...时不带-tags,这样go build会直接忽略带// +build integration的文件 - 注意:
// +build !integration不可靠,Go 构建标签是“至少匹配一个”,不是布尔逻辑,优先用白名单式启用
最易被忽略的一点:build tag 只控制文件是否参与编译,不控制 import 是否被解析——所以即便你用 // +build integration 隔离了文件,只要该文件 import 了某个包,那个包仍可能被 go mod tidy 拉进来。真正干净的做法是:集成测试专用依赖,只出现在带 build tag 的文件里,且这些文件绝不被任何非测试代码 import。

















