我正尝试测试是否按预期顺序调用了模拟对象。下面是简化的示例:
@Test
public void test() {
List<String> mockedList = Mockito.mock(List.class);
for (int i = 0; i < 5; i++) {
mockedList.add("a");
mockedList.add("b");
mockedList.add("c");
}
// I want only this to pass.
InOrder inOrder1 = Mockito.inOrder(mockedList);
inOrder1.verify(mockedList).add("a");
inOrder1.verify(mockedList).add("b");
inOrder1.verify(mockedList).add("c");
// I want this to fail.
InOrder inOrder2 = Mockito.inOrder(mockedList);
inOrder2.verify(mockedList).add("c");
inOrder2.verify(mockedList).add("b");
inOrder2.verify(mockedList).add("a");
}
尽管验证顺序(c -> b -> a
)与调用顺序(a -> b -> c
)不同,但是此测试通过了。这是因为Mockito会验证method2是否在之后的任何地方 method1调用,而不是立即调用(即,之间没有其他调用方法)。当我多次添加元素时,这很有可能。这意味着Mockito InOrder通过b -> a -> c -> a -> c -> b -> c -> b -> a ...
但是我希望此操作失败,并确保订单始终为a -> b -> c -> a -> b -> c -> a -> b -> c ...
更新:正确的验证方法是验证订单的迭代次数是否相同(可接受的答案摘要):
for (int i = 0; i < 5; i++) {
inOrder1.verify(mockedList).add("a");
inOrder1.verify(mockedList).add("b");
inOrder1.verify(mockedList).add("c");
}
// fail the test if we missed to verify any other invocations
inOrder1.verifyNoMoreInteractions();
答案 0 :(得分:2)
问题是您需要添加
inOrder.verifyNoMoreInteractions();
通过循环,您会生成类似
的呼叫随后检查
inOrder.verify(mockedList).add("b");
inOrder.verify(mockedList).add("c");
inOrder.verify(mockedList).add("a");
它与调用(add(b),add(c),add(a))匹配。其他呼叫未选中。
所以我认为您必须选择: 1)验证所有呼叫a,b,c,a,b,c 2)确认您的模拟游戏不再发生互动
顺便说一句,如果您将验证更改为
inOrder.verify(mockedList).add("c");
inOrder.verify(mockedList).add("b");
inOrder.verify(mockedList).add("a");
它将失败,因为它与呼叫不匹配:-)
答案 1 :(得分:0)
这里没有答案:您走错了路(至少对于给定的示例而言):
含义:当创建“ API”时,您想要实现“易于使用,难以滥用”。需要按一定顺序调用方法的API不能实现这一点。因此:感觉需要以编程方式检查订单可能表明您在做“错误的事情”。您应该设计一个“做正确的事”的API,而不是期望代码的用户为您做到这一点。
除此之外:在测试列表时,您绝对不首先要使用模拟。
您要确保元素以特定顺序添加到列表中吗?然后一个简单的
assertThat(actualList, is(expectedList));
这是您的测试应检查的唯一内容!
含义:您无需检查实现细节(add()
以此参数的顺序来调用),您只需检查该操作的可观察结果即可。您不在乎按什么顺序添加事物,也许不在乎重新设置和更新,您只在乎最终结果!
OP给出的评论:当您必须“按顺序”处理某些调用/对象时,则应设计一个界面,以使您传达意图。您只是通过单元测试来测试。当然,这是一个好的开始,但还不够!
基本上,有两个概念可能对您有用:
Command
类(执行“某事”),然后为每个必需的活动创建不同的子类。然后,您的处理器只需创建一个List<Command>
。现在 testing 可以归结为:生成这样的序列,并检查每个条目是否具有给定的类型。