The Mockito文档反复强调它经常是多余的。这在
verify(T)
的Javadoc中以逐字逐句的形式出现,也在
Mockito的主类Javadoc第二部分的代码块中作为多个单行注释出现。
虽然可以验证存根调用,但通常只是多余的。
如果您的代码关心get(0)
返回的内容,那么其他问题会出现(通常甚至在执行verify()
之前就出现)。
如果您的代码不关心get(0)
返回的内容,那么它就不应该被存根。还不信?请看这里。
请注意,最初链接的文章 "
Asking and Telling" 是由Mockito的创始人Szczepan Faber撰写的,可以被视为Mockito设计方面的权威文件。以下是该文章的摘录:
我真的需要重复相同的表达吗?毕竟,存根交互是隐式验证的。我的代码执行流完全免费完成了这项工作。
Aaron Jensen也注意到:
如果您正在验证,则不需要存根,除非该方法返回对测试(或代码)的流程至关重要的内容,在这种情况下,您确实不需要验证,因为流程已经得到验证。
简而言之:没有重复的代码。
但是,如果一个有趣的交互共享了询问和告知的特征呢?我需要在stub()和verify()中重复交互吗?我会得到重复的代码吗?并不是真的。实际上:如果我存根,那么它就是免费验证的,所以我不验证。如果我验证,那么我不关心返回值,所以我不存根。无论哪种方式,
我不会重复自己。然而,在理论上,我可以想象一种罕见的情况,即验证已存根的交互,例如确保存根的交互发生了n次。但这是行为的另一个方面,显然是一个有趣的方面。因此,我想明确表示,并且我非常乐意牺牲一行额外的代码...
自这个问题发布以来,Mockito的最新版本(发布后)已经添加了一些额外的功能,允许或默认为更严格的模拟风格。尽管如此,普遍的期望是通过仅验证无法通过断言或成功测试完成确认的内容来避免脆弱性。
总体而言,Mockito的设计是尽可能地使测试具有灵活性,不是编码实现,而是针对正在测试的方法的规范。虽然您偶尔会看到一个方法调用作为函数规范的一部分(“向服务器提交RPC”或“立即调用传递的LoginCallback”),但更有可能的是您希望验证可以从存根中推断出的后置条件:检查是否调用了getFoo
并不是规范的一部分,只要您将getFoo
存根为返回“foo”,并且数据存储器包含一个其对应属性设置为“foo”的单个对象。
简而言之,显式验证只能从精心制作的存根和后置条件断言中无法推导出的交互是良好的Mockito风格。它们可能是用于无法测量的副作用(如日志记录代码、线程执行器、ArgumentCaptors、多个方法调用、回调函数)的良好调用,但通常不应用于存根化的交互。
doSomething()
不再调用getFoo()
或者只是将其注释掉,那么怎么知道呢?如果您没有验证方法调用,那么您将无从得知。 - Taj Ahmedverify()
,有没有办法使测试失败,如果模拟的方法未被调用? - GlideMockito.when
(参见http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#2)。 - aro_tech