手动 mock 最轻量但需自管验证;testify/mock 适合中型项目,语法直观但性能损耗大、并发易出错。
手动实现 Mock 接口最轻量,但得自己管调用验证
Go 没法直接 patch 结构体方法,所以必须先定义接口(比如 UserRepository),再写个结构体去实现它。这是所有 Mock 的起点,也是最可控的方式。
常见错误是忘记处理 nil 返回或漏实现某个方法,导致测试 panic;更隐蔽的坑是 mock 行为写死在结构体字段里,没法按不同测试用例动态切换。
- 适合小项目、单个接口、逻辑简单场景
- 不依赖第三方库,零额外编译开销
- 无法自动校验“是否被调用”“调用了几次”,得靠自己加计数器或布尔标记
- 示例中用闭包赋值
mockGetUser函数,比固定字段更灵活
testify/mock 适合中型项目,写法直观但性能有损耗
它靠 mock.Mock 基类 + Called()/On().Return() 实现行为录制与回放,语法接近行为驱动风格,上手快。
容易踩的坑:反射调用带来明显性能开销(基准测试显示比手动 stub 慢 20–40 倍),并发测试时可能因共享 controller 状态出问题;另外 AssertExpectations(t) 忘写会导致 mock 调用未被检查,测试“假通过”。