Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何在模拟时不使用接口?_Go_Testify - Fatal编程技术网

Go 如何在模拟时不使用接口?

Go 如何在模拟时不使用接口?,go,testify,Go,Testify,我试图避免使用接口,因为我的用例不需要它(类似于中提到的)。然而,要创建一个mock(使用验证),我不需要一个接口来mock吗?我可以创造一个,但它似乎乏味。我的代码使用的所有地方都需要编写接口来模拟,而不是实际使用。有解决方法吗?您需要一个接口来模拟,因为模拟是您的第二个实现,所以如果您在单元测试中使用模拟,那么您的用例确实需要它。该接口用作占位符,用于填充该功能的某些实现。您计划至少有两个这样的实现:一个模拟,一个生产。为了能够互换使用它们进行测试,您必须使用接口。如果接口的唯一可能用途是用

我试图避免使用接口,因为我的用例不需要它(类似于中提到的)。然而,要创建一个mock(使用
验证
),我不需要一个接口来mock吗?我可以创造一个,但它似乎乏味。我的代码使用的所有地方都需要编写接口来模拟,而不是实际使用。有解决方法吗?

您需要一个接口来模拟,因为模拟是您的第二个实现,所以如果您在单元测试中使用模拟,那么您的用例确实需要它。该接口用作占位符,用于填充该功能的某些实现。您计划至少有两个这样的实现:一个模拟,一个生产。为了能够互换使用它们进行测试,您必须使用接口。

如果接口的唯一可能用途是用于测试,我同意,这可能是一个糟糕的接口,您应该避免这种情况

最好的方法是重构系统,使其依赖于一个小而有用的接口,而不是对过于复杂的结构进行一次性的“模拟”。一个很好的例子是
net.Listener
接口。在
net.Listener
之上构建的系统很容易模仿,是的,但这不是实现
net.Listener
的原因。您之所以使用该接口,是因为它允许您交换许多可能的实现,其中一个恰好用于测试

另一个强大的方法是将函数链接在一起,而不是将函数硬编码为方法
http.HandlerFunc
就是一个很好的例子,它也展示了很好的界面设计。查看返回
http.Handler
的许多“click-together”函数,而不是一个大型的“Handler”结构,然后您必须模拟它进行测试。这是最好的

记住函数在Go中是一流的,通过传递和返回函数而不是将它们绑定到接口,您可以获得很大的灵活性。当您这样做时,您还可以将它们捆绑在一起作为一个结构。这可以提供很多功能,这些功能恰好对测试也很有用。例如,请参阅,
tls.Config
,它允许您包括自己的
GetCertificate
函数(以及其他函数)。但是
tls.Config
struct也有合理的默认值,因此您不必每次都配置每一部分。通过传递专门版本的
tls.Config
,您可以在不“模拟”任何内容的情况下测试tls功能


这里一致的主题是使您的系统在其实现方面具有灵活性,并且作为一个好的副作用,它使测试更容易。根据我的经验,这是一种比模拟更好的思考问题的方法。

为了减少模拟较大接口的重复次数,似乎可以使用类似于
vectra/mockery
的方法来生成模拟。然而,这不是一个消除对接口需求的解决方案,但我认为Rob在下面提到了一些好主意。

“我的用例不需要它”——这不是真的。测试需要它。测试是一个用例。您可以尝试使用
pure
功能风格,但不要使用验证,而是进行正常测试。True。这很有道理,谢谢!还在这里学习更多。有趣的是,可以将函数用作“适配器”。另外,还有一个有趣的点是
tls.Config
。似乎可以从本质上为客户机生成“mock”,因此他们不需要模拟任何东西。