手写 fake 更快更稳适用于内部接口gomock/testify/mock 仅适用于外部模块或方法超10个、需严格校验调用顺序的场景。什么时候该手写 fake而不是用 gomock 或 testify/mock绝大多数 Go 项目里**手写 fake 结构体比生成 mock 更快、更稳、更容易调试**。gomock/testify/mock 的价值只在特定场景你要 mock 的接口来自外部 module比如 cloud.google.com/go/storage.Client且它没提供可替换的 interface或者你的接口方法超过 10 个、变更频繁、需要严格校验调用顺序和参数匹配。常见错误现象mockgen 生成一堆代码却只用其中 1 个方法测试里反复写 mockRepo.EXPECT().Get(...).Return(...)但业务逻辑根本没用到 Get 的第二个参数改了接口签名后忘记重跑 mockgen导致编译失败或 panic。手写 fake 适合自己定义的 Notifier、UserRepository、PaymentService 等内部接口fake 只需实现你真正调用的方法不用管其他“理论上存在”的方法字段可导出如 Called bool、LastTo string测试中直接断言不依赖 AssertExpectations 这类黑盒机制如果要模拟并发行为嵌入 sync.Mutex 就行不用学 gomock 的 Times(3) 语法HTTP 客户端测试别碰 http.DefaultClient用 httptest.Server 替代硬编码 http.Get 或直接 new http.Client{} 是 mock 失败的根源——它让测试强依赖网络、第三方服务状态CI 上随机超时、404、SSL 错误全来了。正确做法是把请求入口抽成可配置字段测试时注入 httptest.Server.URL立即学习“go语言免费学习笔记深入”type UserClient struct { BaseURL string Client *http.Client}pfunc (c emUserClient) GetByID(ctx context.Context, id string) (/emUser, error) {resp, err : c.Client.Get(c.BaseURL /users/ id)// ...}测试中启动服务器server : httptest.NewServer(handler)然后 defer server.Close()务必传 server.URL 给被测 client不是拼接字符串避免路径不一致handler 中用 json.NewEncoder(w).Encode(...) 返回响应别用 raw string否则 Content-Type 缺失导致解析失败若被测代码已固定用 http.DefaultClient 且无法改才考虑 httpmock但它对自定义 Transport 无效且不报错——这是最隐蔽的坑数据库 mock 别绕开 sqlmock但得会写靠谱的 SQL 匹配sqlmock 是目前最成熟、最贴近真实 *sql.DB 行为的方案。它不 mock 接口而是 mock database/sql 底层交互所以能覆盖事务、预处理语句、多行查询等真实场景。 Mokker AI AI产品图添加背景