使用testify/mock在Go中无法调用Mock方法的问题
testify/mock在Go中无法调用Mock方法的问题
兄弟,我太懂你这种踩坑的憋屈感了!你现在的问题核心就是代码耦合得太死——你的MyData()方法直接硬调用了自身结构体的MySub(),完全没做接口解耦,这就导致哪怕你用testify生成了mock结构体,真实的MyData()还是会拽着真实的MySub()跑,根本不搭理你设置的mock期望。
给你捋个清晰的解决思路,几步就能搞定:
- 先做接口抽象:把你要mock的
MySub()单独抽成一个接口,比如叫SubProvider,里面就放这一个方法就行。 - 解耦依赖关系:把原来的结构体改成依赖这个接口,要么把接口作为
MyData()的参数,要么给结构体加个对应接口类型的字段(更推荐后者,代码更整洁)。 - 调整
MyData()的实现:让它调用结构体实例.接口字段.MySub(),而不是直接结构体实例.MySub()。这样一来,MyData()就不再绑定自身的MySub(),而是依赖你传入的任意接口实现。 - 测试时mock接口:用testify/mock生成一个实现了
SubProvider的mock结构体,给它的MySub()设置好返回期望,再把这个mock实例赋值给原结构体的接口字段,这时候调用MyData()就会走你设置的mock方法了!
给你贴个简化的代码示例,一看就明白:
首先是业务代码的调整:
// 第一步:定义承载MySub的接口 type SubProvider interface { MySub() string } // 原结构体现在依赖SubProvider接口 type MyStruct struct { Subber SubProvider // 把接口作为结构体字段 } // 原MySub可以作为默认实现,供生产环境使用 func (s *MyStruct) MySub() string { return "真实的MySub返回内容" } // 调整MyData的实现,调用依赖的接口方法 func (s *MyStruct) MyData() string { // 这里不再直接调用s.MySub(),而是调用接口的MySub return s.Subber.MySub() }
然后是测试代码:
import ( "testing" "github.com/stretchr/testify/mock" ) // 用testify生成mock结构体,实现SubProvider接口 type MockSub struct { mock.Mock } // 实现接口要求的MySub方法 func (m *MockSub) MySub() string { args := m.Called() return args.String(0) } func TestMyData_UseMockSub(t *testing.T) { // 初始化mock实例 mockSub := new(MockSub) // 设置期望:调用MySub时返回"mock的MySub返回内容" mockSub.On("MySub").Return("mock的MySub返回内容") // 初始化原结构体,把Subber字段设为我们的mock实例 testStruct := &MyStruct{Subber: mockSub} // 调用要测试的MyData方法 result := testStruct.MyData() // 验证结果是否符合预期 if result != "mock的MySub返回内容" { t.Fatalf("期望返回'mock的MySub返回内容',实际得到'%s'", result) } // 验证mock的方法是否被正确调用了 mockSub.AssertExpectations(t) }
为啥之前不行?因为你原来的MyData()和MySub()是硬绑定在同一个结构体上的,testify的mock没办法拦截这种直接的结构体方法调用——它的mock能力是基于接口的,或者只能完全替换整个结构体的方法,但那样你就没法测试真实的MyData()逻辑了,解耦才是破局的关键!
备注:内容来源于stack exchange,提问作者jagat singh
相关产品推荐
相关产品推荐

