必须确保包路径、接口可见性、context处理和并发安全四点对齐,否则编译失败或测试不可靠;常见错误包括package声明错位、context实例误匹配、复用mock实例引发竞态、//go:generate注释位置或扫描范围不当。

mockery 生成的 mock 文件能直接用,但**必须确保包路径、接口可见性、context 处理和并发安全这四点对齐,否则编译失败或测试行为不可靠**。
mockery 生成后报 undefined: XxxMock?检查 package 声明是否错位
这是最常见编译错误,本质是 mockery 推断的包名与实际模块路径不一致。比如接口定义在 github.com/yourorg/app/internal/service,但你在 internal/service 目录下运行命令,它会生成 package service,而 Go 模块要求 import 路径完整,导致类型无法识别。
- 始终在模块根目录(含
go.mod的目录)下执行mockery命令 - 显式指定
--inpackage:它会让生成文件使用当前目录的包名,而非推断值 - 跨包引用时加
--recursive,并确认go mod vendor或replace已就绪 - 生成后手动检查生成文件顶部的
package xxx和// import "xxx"注释是否匹配真实路径
接口方法含 context.Context,Mock.On() 匹配总失败?别传具体 context 实例
mockery 不会自动处理 context.Context 的语义相等性——context.Background() 和 context.TODO() 是不同实例,哪怕它们都“空”,mock.On("Method", ctx, "arg") 也绝不会命中。
- 一律用
mock.Anything占位:mockObj.On("Do", mock.Anything, "arg").Return(nil) - 若必须校验 context 内容(如是否含特定 key),改用
mock.MatchedBy(func(v interface{}) bool { ... }) - 不要在测试中构造新 context 传入被测函数再期望它和 mock 中预设的 context 相等——这不是 context 的用法
go test -race 报 data race 在 mock.calls?避免复用同一 mock 实例
mockery 生成的 struct 默认无锁,On()/Return() 和 AssertExpectations() 都操作内部切片 calls,并发调用必然触发竞态。
- 单元测试里禁止用同一个 mock 实例启动多个 goroutine
- 每个 goroutine 应创建独立 mock 实例(哪怕逻辑相同)
- 真需共享状态,手动加
sync.Mutex包裹mockObj.On()等调用,或换用gomock(其Controller默认线程安全) - 报错指向
mock.calls = append(...)就是这个原因,不是代码写错了,是用法越界了
//go:generate mockery 注释没生效?位置、目录、扫描范围三者缺一不可
//go:generate 不是魔法,它依赖 go list 能扫描到该文件,且注释必须紧贴接口定义。
- 注释必须在接口定义正上方,中间不能有空行或其它语句
- 文件名不能以
_test.go结尾(go generate默认忽略测试文件) - 执行
go generate ./...时,当前目录必须是模块根目录,否则子目录下文件可能被跳过 - 不确定是否生效?先运行
go list -f '{{.ImportPath}}' ./...看目标文件是否出现在输出里
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











