【发布时间】:2021-03-24 09:38:24
【问题描述】:
我认为依赖注入而不是全局变量的原因之一是在测试期间很难模拟全局变量。但是假设我将全局声明为接口,我可以避免这个问题。
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)
那么考虑到简单性,这种使用全局接口的方法不是比使用依赖注入更好吗?
【问题讨论】:
-
开场白对我来说听起来很奇怪:一个精心设计的 Go 程序不包含全局变量,也不使用 DI——相反,您使用接口来为您的关键对象指定行为契约'想要有多个可交换的实现,包括用于测试,然后你有简单无聊的代码,它创建必要类型的对象并将它们传递给创建其他对象的代码等 - 所有一直到“叶子”对象。后者是 DI fluff 在其掩护下所做的。
-
这太奇怪了。为什么要模拟 http.Client?
-
@Volker 你将如何测试一段调用外部 API 的代码。如果我不模拟它,它会使实际的 http 调用本身正确吗?
-
«如何测试一段调用外部 API 的代码。»通常你会在
httptest.Server的帮助下做到这一点。 -
当然你不会调用一些有副作用的外部API。当然,您调用外部 API 的本地存根或伪造。问题不是“在测试期间对非无副作用的 3rd 方 API 进行实际 HTTP 调用有什么问题?”但是“在测试期间进行实际的 HTTP 调用有什么问题?”因为那个 call 是你可以用你奇怪的模式省略的。对不起,如果我不清楚。按照 kostix 的说明设置本地存根/伪造文件。不要嘲笑。
标签: unit-testing go dependency-injection interface global