使用Gomock时未导出interface作为方法参数无法访问如何解决
直接将生成的MockBoo的MethodB入参类型替换为Mockfoo不可行,Go要求接口实现的方法签名必须完全匹配,修改参数类型后MockBoo将不再实现原Boo接口,会触发新的编译错误。
可行解决方案
方案1:将mock代码生成到原接口所在包内
这是成本最低的方案,不需要修改任何业务代码。生成mock时指定输出包名和原接口所在包一致,且将生成的mock文件存放到原包目录下,mock代码和未导出的foo接口属于同一个包,天然可以访问未导出类型。
- 生成命令示例:
# 假设原接口定义在pkg/foo包下的boo.go文件中 mockgen -source=pkg/foo/boo.go -destination=pkg/foo/mock_boo.go --package=foo
方案2:调整原接口的导出性(可修改业务代码时优先选择)
原代码设计本身存在不合理性:对外导出的Boo接口的MethodB方法使用了未导出的foo作为参数类型,就算不用mock,外部包也根本没法正常调用MethodB方法,因为外部包无法构造foo类型的参数。
直接将foo接口改为导出的Foo即可从根源解决问题,后续不管是正常调用还是生成mock都不会有类型访问问题。
方案3:使用接口鸭子类型做桥接(既不能改业务代码也不想把mock放到原包时使用)
Go的接口是鸭子类型,只要两个接口的方法签名完全一致,就可以互相转换。你可以在测试所在包声明一个和原foo接口方法完全一致的导出接口,再做一层转换即可:
// 测试包内声明导出的接口,方法签名和原未导出foo完全一致 type TestFoo interface { MethodA() int } // 转换函数,假设原包别名为origpkg func toOrigFoo(t TestFoo) origpkg.foo { return t.(origpkg.foo) }
测试时先构造你自己的TestFoo实现(也可以用mockgen生成这个TestFoo的mock),调用转换函数转成原foo类型后再传入MethodB即可。
内容的提问来源于stack exchange,提问作者kito
相关产品推荐
相关产品推荐

