1

我想使用 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 的可能性。我想创建一个类似的 VerificationModebeforeAnyOther并像这样使用它:

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

目的是验证begin首先被调用,并且在和之间没有相关的交互endflush而在和之间的交互beginend指定。

我一直在研究现有 VerificationModes 的源代码,似乎原则上这应该是一个简单的 VerificationMode 来实现,但是一旦我超越了 Mockito 的一些主要类,文档就会变得非常薄,几乎就像它试图告诉我一样我不应该接触这些课程。我特别警惕那些开始的包,org.mockito.internal因为像这样的名字向我暗示,即使它们是公共的,这些类也可能会发生变化。

实现 VerificationMode 的真正重要的类似乎都在org.mockito.internal.verification.api包中。整个包似乎只有一点 javadoc,上面写着:“一旦验证 API 完全完成,这个包应该向公众开放。” 这是否意味着这个包正在被积极修改,所以我不应该使用它包含的任何东西,或者这只是它多年来所说的东西,而且这个包可能永远不会真正改变?

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

4

1 回答 1

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()在之间的某个时间点调用beginflush但无论该调用是在调用 之前还是之后都没有关系,那么您就不end走运了。

您可以在其他一些模拟库中处理这种情况。EasyMock 使这变得最简单——例如,对于begin先到后到的序列flush,我们不关心中间的调用:

DrawTool mock = EasyMock.createMock(DrawTool.class);
EasyMock.checkOrder(mock, true);
mock.begin();
EasyMock.expectLastCall();
EasyMock.checkOrder(mock, false);
mock.end();
EasyMock.expectLastCall();
EasyMock.expect(mock.someOtherCallThatReturnsAValue()).andReturn(null);
EasyMock.checkOrder(mock, true);
mock.flush();
EasyMock.expectLastCall();
EasyMock.replay(mock);

new Drawer().draw(tool);

EasyMock.verify(mock); 

在 JMock 2 中,一个等效的测试似乎是可能的,如果笨拙的话。在 JMock 1 中它更容易一些 ,但是那个库已经过时了(大约 JDK 1.3),所以不要使用它。这在 Moxie 中是不可能的(免责声明/无耻插件:我是作者),但现在有一个待办事项列表项

我不能代表 Mockito 开发人员解释为什么 Mockito 验证 API 文档是这样的——最好在邮件列表中询问他们。我敢肯定他们会欢迎补丁。

于 2013-11-01T21:03:37.630 回答