为Mockito创建自定义VerificationMode类

时间:2013-10-19 03:48:53

标签: java unit-testing mocking mockito

我想使用Mockito来验证一些事情,但研究文档让我相信,如果不超出通常的Mockito工具,这是不可能的。以此为例:

DrawTool tool = mock(DrawTool.class);
new Drawer().draw(tool);
verify(tool).begin(); // Make sure begin and end are called exactly once each
verify(tool).end();
InOrder inOrder = inOrder(tool);
inOrder.verify(tool).begin();
inOrder.verify(tool).end();
inOrder.verify(tool).flush();
inOrder.verifyNoMoreInteractions();

此测试可以很好地验证多项内容,例如验证flush是最后一次互动,但似乎Mockito无法验证begin是否是第一次互动。我对Mockito工具中的不对称感到惊讶,所以我正在调查创建自定义VerificationModes的可能性。我想创建一个名为beforeAnyOther的VerificationMode,并像这样使用它:

inOrder.verify(tool, beforeAnyOther()).begin();
inOrder.verify(tool).end();
inOrder.verify(tool, beforeAnyOther()).flush();
inOrder.verifyNoMoreInteractions();

目的是确认首先调用begin并确保endflush之间没有相关的互动,同时保留begin和{{之间的互动1}}未指定。

我一直在研究现有VerificationModes的源代码,原则上这应该是一个简单的VerificationMode来实现,但是一旦我超越了Mockito的几个主要类,文档变得非常薄,几乎就像它正在尝试告诉我,我不应该接触这些课程。我特别警惕那些以end开头的软件包,因为这样的名字告诉我这些类即使是公开的,也会发生变化。

实现VerificationMode的真正重要的类似乎都在org.mockito.internal包中。整个软件包似乎只有一点javadoc,并且它说,“一旦验证API完全完成,这个软件包应该向公众开放。”这是否意味着这个软件包正在被主动修改,因此我不应该使用它包含的任何东西,或者它只是它已经说了多年的东西而且软件包可能永远不会真正改变?

如果我不能使用org.mockito.internal.verification.api中的类,那么似乎无法实现自定义VerificationModes。有没有办法在没有自定义VerificationModes的情况下做这样的事情?

1 个答案:

答案 0 :(得分:2)

如果您可以完全指定模拟中发生的调用顺序,那么您将不需要beforeAnyOther验证模式。例如,假设您期望的行为是......

  • begin被调用一次,然后
  • end被调用一次,然后
  • flush被召唤一次
  • tool
  • 上没有其他来电

然后应该做以下工作:

// Verify that the three invocations arrived in the desired order.
InOrder inOrder = inOrder(tool);
inOrder.verify(tool).begin();
inOrder.verify(tool).end();
inOrder.verify(tool).flush();

// Verify that the three invocations are all we received.
Mockito.verify(tool).begin();
Mockito.verify(tool).end();
Mockito.verify(tool).flush();
Mockito.verifyNoMoreInteractions();

另一方面,如果你有任何额外的电话发生在你要验证的序列之外,那么你是正确的,Mockito目前无法验证。例如,如果您知道必须在tool.setPenColor()begin之间的某个时间点拨打flush,但是在调用{{1}之前或之后调用此呼叫无关紧要你不幸运。

您可以在其他一些模拟库中处理这种情况。 EasyMock使这最简单 - 例如,对于end首先出现的序列,begin是最后一个,我们不关心中间的调用:

flush

在JMock 2中,如果不实用,似乎有可能进行等效测试。它在JMock 1中是bit easier,但该库是过时的(大约是JDK 1.3),所以不要使用它。这在Moxie中是不可能的(免责声明/无耻插件:我是作者),但现在有一个todo list item

我不能代表Mockito开发人员说明为什么Mockito验证API文档是这样的 - 最好在邮件列表中询问它们。我相信他们会欢迎补丁。