是否没有必要验证与Mockito中被模拟的方法相同的方法?

Gli*_*ide 7 java unit-testing mockito

我经常看到相同的方法被验证为被模拟的方法Mockito(下面的例子).Mockito.verify()在这些情况下打电话有什么额外的好处吗?

//mock method
FooService fs = mock(FooService.class);
when(fs.getFoo()).thenReturn("foo");

//method under test
fs.doSomething();

//verify method
verify(fs).getFoo();
Run Code Online (Sandbox Code Playgroud)

如果fs.getFoo()未调用,该方法应该失败.为什么打电话verify?如果您需要ArgumentCaptor在验证中使用断言参数,我会看到好处; 除了ArgumentCaptor案,它是否只是不必要的?

Jef*_*ica 9

Mockito文档反复说它通常是多余的.这在verify(T)Javadoc中逐字显示为Mockito主类Javadoc第2节中代码块中的多个单行注释:

虽然可以验证存根调用,但通常它只是多余的.如果你的代码关心什么get(0)返回,那么其他东西就会中断(通常甚至在verify()执行之前).如果你的代码不关心什么get(0)返回,那么它不应该被存根.不相信?看到这里.

请注意,链接的文章" 询问和讲述 "由Mockito创始人Szczepan Faber撰写,可以被认为是Mockito设计中的权威文件.摘自该帖子:

我真的要重复同样的表达吗?毕竟,隐含地验证了存根交互.我自己的代码的执行流程完全免费.Aaron Jensen也注意到:

如果您正在验证您不需要存根,除非该方法返回对您的测试(或代码)流程至关重要的方法,在这种情况下您实际上不需要验证,因为流程将具有验证.

回顾一下:没有重复的代码.

但是如果一个有趣的互动分享了询问和说话的特征呢?我是否必须在stub()和verify()中重复交互?我最终会得到重复的代码吗?并不是的.在实践中:如果我存根,那么它是免费验证的,所以我不验证.如果我验证然后我不关心返回值,所以我不存根.无论哪种方式,我都不重复自己.但从理论上讲,我可以想象一个罕见的情况,我确实会验证存根交互,例如确保存根交互恰好发生n次.但这是行为的一个不同方面,显然是一个有趣的方面.因此,我想要明确,我非常乐意牺牲一行额外的代码......

总的来说,Mockito的设计是允许测试尽可能灵活,编码不是实现,而是编码您正在测试的方法.虽然您偶尔会看到一个方法调用作为函数规范的一部分("向服务器提交RPC"或"立即调用传递的LoginCallback"),但您更有可能想要验证后置条件.从存根推断:getFoo只要您存根getFoo返回"foo"并且数据存储包含一个对应属性设置为"foo"的单个对象,那么检查被调用的实际上并不是规范的一部分.


简而言之,只有明确地验证精心设计的存根和后置条件断言不能隐含的交互才被认为是良好的Mockito风格.它们可能是对其他不可测量的副作用的良好调用 - 日志代码,线程执行器,ArgumentCaptors,多个方法调用,回调函数 - 但通常不应用于存根交互.