由于外部库不公开接口(因此不是可模拟的),而仅公开纯函数,因此我很难在Go中编写单元测试。即使像Google这样的大公司也没有,所以我想知道我的方法是否足够好。库interface
不是提供s而不是仅提供函数的包以便用户模拟它们的好习惯吗?
到目前为止,我想出的解决方案是将这些包与接口的实现包装在一起,但这似乎工作量太大。
我举一个例子。我的功能可能看起来像这样
func AnyFunction() error {
sess := session.Get("blabla")
// logic in here...
}
Run Code Online (Sandbox Code Playgroud)
其中session是一个导入的包,返回struct
。我不能嘲笑包裹session
。对于这种情况,我将编写一个SessionInterface
带有内部调用session的实现。
例如:
type SessionInterface interface {
Get(s string) Session
}
type mySessionImpl struct {}
func (me *mySessionImpl) Get(s string) Session {
return session.Get(s)
}
Run Code Online (Sandbox Code Playgroud)
现在,为了进行测试,我可以模拟SessionInterface并将其注入我的代码中
你在这里做的是正确的事情,这是语言设计者有意识的决定。
Go 的哲学是你的代码应该“拥有”这些接口,而不是库。在像 C# 和 Java 这样的语言中,库预先定义了它们的接口,而并不真正了解使用者的实际需要。(也许它们包含的方法太多,或者太少。)在 Go 中,因为消费者有效地“拥有”接口,您有权指定哪些方法实际上需要出现在最小的接口中,以及程序需求的变化意味着您还可以更改界面。
现在在这种特殊情况下,为了可测试性在函数前面创建适配器似乎很奇怪,但请考虑替代方案:如果session.Get()
是接口或结构的方法,而不是函数,它将强制所有库使用者实例化一个虚拟对象以调用该方法。不是每个人都会假装它 - 他们更容易说想要(像您一样)的消费者有权编写适配器,而那些不这样做的消费者可以幸福地忽略它们。