单元测试必须隔离外部依赖,否则不是单元测试;需用接口抽象依赖、禁用init()、避免共享状态、序列化逻辑不用真实HTTP服务;集成测试须用构建标签控制、临时DB实例、独立schema;Micro测试重状态验证而非连接;覆盖率需覆盖error分支。

单元测试必须隔离外部依赖,否则不是单元测试
Go里写单元测试最常犯的错误,就是把database/sql、http.Client或redis.Client直接 new 出来塞进测试逻辑里。这会导致测试变慢、随机失败、无法并行——本质上已经不是单元测试了。
- 用接口抽象依赖:比如把
*sql.DB换成OrderRepository接口,再用内存实现(如inmem.OrderRepo)或gomock生成 mock - 禁用
init()和包级变量初始化:它们会在所有测试前执行一次,污染状态;改用函数式初始化,在每个测试里显式调用 -
t.Parallel()可以开,但前提是测试间无共享状态(比如共用一个全局 map 或 channel) - 序列化逻辑不用起真实 HTTP 服务:用
json.Marshal/json.Unmarshal+ 字段断言就足够验证结构体行为
集成测试要用构建标签控制开关,避免本地误跑
集成测试要连真实 PostgreSQL、RabbitMQ 或 Redis,但绝不该在你敲go test时自动触发。硬编码localhost:5432或复用.env配置,等于把开发机当测试机用。
- 加
//go:build integration构建标签,并在测试函数上写// +build integration - 启动命令明确带
-tags=integration:go test -tags=integration ./... - DB 连接字符串从
os.Getenv("TEST_DB_URL")读,本地设为postgres://test:test@localhost:5432/test?sslmode=disable - 每次测试前用
docker run --rm -d -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres:15拉临时实例,结束自动销毁 - 每个测试用例创建独立 schema(如
CREATE SCHEMA test_123),别往public里写数据
Go Micro 微服务测试别测“连得上”,要测“状态变了没”
RPC 和事件流测试最容易陷入“只要不 panic 就算过”的陷阱。Micro 的broker.Publish或client.Call成功返回,不代表业务逻辑真被触发了。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 注册中心换成内存版:
micro.NewService(micro.Registry(registry.NewRegistry())) - Broker 用
broker.NewMemoryBroker()捕获消息,然后断言topic、payload、headers是否符合预期 - RPC 测试时 client 和 server 启在同一进程,用
service.Server().Options().Address拿到监听地址,再构造micro.NewClient() - 重点验证副作用:比如下单后查数据库,确认
order.status变成"processing",而不是只看err == nil
覆盖率报告漏掉 error handling?表格驱动必须显式覆盖
go test -cover 显示 85%,不等于代码健壮。很多团队上线后一遇超时或磁盘满就 panic,就是因为 error 分支根本没跑过。
立即学习“go语言免费学习笔记(深入)”;
- 表驱动测试里必须有
{name: "context timeout", mock: func() error { return context.DeadlineExceeded }}这类 case - 不要只 mock 成功路径;对每个外部调用点(DB 查询、HTTP 请求、文件读写),都准备至少一个失败 case
- 错误类型要具体:用
errors.Is(err, os.ErrNotExist)断言,而不是err != nil - 注意
defer里的 panic:如果 cleanup 函数里有os.Remove且未处理 error,可能掩盖主逻辑错误
GetUser之前先补上{name: "user not found", userID: 999, expectedErr: true}。这个习惯一旦松动,mock 就会退化成摆设,集成测试就变成定时炸弹。

















