mockgen的-source必须指向接口定义的.go文件,-package需与测试文件import路径严格一致;gomock.Controller须每测独享,gRPC mock需显式处理ctx参数;应使用go.uber.org/mock而非已归档的旧版。

mockgen 生成 mock 代码时 -source 和 -package 参数怎么配?
生成失败或编译报错,八成是这两个参数没对齐。关键不是“填什么”,而是它们和真实代码的包结构必须严格一致。
-
-source必须指向定义接口的 .go 文件(比如user.go),不能是目录,也不能是已编译的包路径 -
-package要和目标 mock 文件将来被 import 的位置匹配:如果测试文件在sample包里,且你打算用import "your/project/sample",那这里就得写-package=sample - 生成的
mock_user.go文件顶部的package声明必须和-package一致,否则 go build 会直接拒绝 - 常见坑:接口定义在
internal/service下,却用-package=main,结果 mock 类型无法被测试文件识别
gomock.Controller 的生命周期管理为什么不能复用?
每个测试函数都该有自己的 gomock.Controller 实例,复用会导致期望(EXPECT)状态污染、panic 或静默失败。
-
gomock.NewController(t)应该放在测试函数开头,t是*testing.T;它内部绑定了t.Helper()和 cleanup 逻辑 - 如果把 controller 提到全局变量或 test helper 函数外层,多个测试并发跑时,
Finish()可能提前触发,或某个测试的EXPECT被另一个测试覆盖 - 真正要复用的是 mock 对象本身(比如
mockUserService),但它的 controller 必须独占 - 错误现象:
Unexpected call to *mocks.MockUserService.GetUser却没调用过 —— 很可能是 controller 被其他测试提前 Finish 了
gRPC 接口 mock 时为什么总卡在 context deadline?
不是网络问题,是 mock 没正确处理 context.Context 参数。gRPC 方法签名里带 ctx context.Context,mock 必须显式接收并返回,否则调用方会等超时。
- 接口定义里如果有
GetUser(ctx context.Context, id int) (*User, error),生成的 mock 方法签名也必须含ctx参数 - 设置期望时别漏掉
ctx:mockUserService.EXPECT().GetUser(gomock.Any(), 123).Return(...),第一个参数必须是gomock.Any()或具体 ctx - 别用
nil传 ctx —— gRPC 客户端底层会检查,直接 panic - 如果想模拟超时,就让 mock 返回
context.DeadlineExceeded错误,而不是靠外部 context.WithTimeout 控制
go.uber.org/mock 和 github.com/golang/mock 有什么实质区别?
后者已归档停更(2024 年起),前者是当前唯一维护分支,API 兼容但工具链路径和导入路径不同 —— 混用会导致构建失败。
立即学习“go语言免费学习笔记(深入)”;
- 安装命令必须用
go install go.uber.org/mock/mockgen@latest,旧命令github.com/golang/mock/...现在拉不到有效版本 - 生成代码里的 import 路径是
go.uber.org/mock/gomock,不是github.com/golang/mock/gomock - 两者生成的 mock 结构体字段名、方法签名一致,但 controller 初始化方式略有差异:新版本推荐
gomock.NewController(t),旧版有时用gomock.NewController(nil)+ 手动 defer - 最易忽略的点:
go.mod里必须 replace 或 requirego.uber.org/mock,否则go test会因找不到符号失败
go.mod 的依赖声明,或者测试文件 import 路径和生成时指定的 -package 对不上 —— 这类错误不报语法问题,只在运行时提示 “undefined: MockXXX”。


















