Go语言使用GoMock测试:是否需修改生成的Mock文件?
关于GoMock测试的核心疑问解答
核心结论:绝对不要修改GoMock生成的mock文件
GoMock生成的文件是自动生成的产物,每次执行mockgen命令都会完全覆盖原有内容,你手动添加的代码会全部丢失。而且修改生成文件违背了mock工具的设计初衷——它的作用是模拟依赖的行为,而非替代真实实现。
你的困惑拆解与解决方法
你混淆了「被测试逻辑」和「依赖的mock/真实实现」的边界,下面分点说明:
1. 明确测试目标
你要测试的是User.GetUserInfo方法,它的核心逻辑是调用依赖的Person.Male.Get方法,并直接返回其结果。测试这个方法时,GoMock的作用是模拟Person.Male.Get的不同行为(比如返回成功、返回特定错误),从而验证User.GetUserInfo是否正确传递参数、返回结果,而不是让User自己去实现Person.Male的Get方法。
2. 如何加入自定义的Get实现?
如果你需要一个真实的Person.Male接口实现(而非mock),不需要碰mock文件,自己写一个结构体实现该接口即可:
// 自定义Male接口实现 type CustomMale struct{} func (c *CustomMale) Get(id int64) error { if id == 2 { return func1() // 替换为你的实际业务逻辑 } else { return func2() } }
之后不管是业务代码还是测试代码,直接把这个自定义实例传给NewUser就行:
// 业务代码中使用真实实现 user := NewUser(&CustomMale{}) err := user.GetUserInfo(2) // 测试代码中如果需要用真实实现验证逻辑,也可以这么用
3. 正确使用GoMock的场景
当你需要模拟Person.Male.Get的特定行为来测试User.GetUserInfo的分支逻辑时,才需要用到GoMock。比如测试User.GetUserInfo在Person.Get返回错误时的表现:
func TestUser_GetUserInfo(t *testing.T) { ctl := gomock.NewController(t) defer ctl.Finish() mockMale := mock.NewMockMale(ctl) testID := int64(1) expectedErr := errors.New("failed to get info") // 设置mock期望:调用Get(testID)时返回expectedErr mockMale.EXPECT().Get(testID).Return(expectedErr) user := NewUser(mockMale) err := user.GetUserInfo(testID) // 断言返回的错误是否符合预期 if err != expectedErr { t.Errorf("expected error %v, got %v", expectedErr, err) } }
内容的提问来源于stack exchange,提问作者HC LW
相关产品推荐
相关产品推荐

