我认为,与全局变量相比,更喜欢依赖注入的原因之一是在测试过程中很难模拟全局变量。但假设我将全局声明为接口,我可以避免这个问题。
package restclient
type HTTPClient interface {
Do(req *http.Request) (*http.Response, error)
}
var (
Client HTTPClient
)
func init() {
Client = &http.Client{}
}
在上面的例子中,我正在创建一个全局接口,并将其初始化为http客户端。因此,每当我想进行REST调用时,我都会使用这个接口。现在,在我的测试案例中,如果我想模拟http客户端,我所需要做的就是
restclient.Client = new(RestclientMock)
那么,考虑到简单性,这种使用全局接口的方法不是比使用依赖注入要好得多吗?
当考虑并行运行多个测试时,这种方法在测试方面的问题开始变得清晰起来。
一个测试会将全局变量设置为能够使用它进行测试,在测试时,它会被下一个测试覆盖,从而导致两个测试的行为都不可预测。它们现在使用相同的依赖实例相互影响。
注意:实际上,您甚至可以在不启用测试并行执行的情况下遇到这个问题。特别是如果依赖项具有内部goroutine,这些goroutine可能在为其创建的测试执行之后仍然存在。