在Mockito中,我们有一种情况,即列表的捕获不会返回预期的结果。测试用例:
在我们的断言中,我们只期望"Pip“在那里,而"Sok”也在那里。我们认为这是不正确的,因为在抓捕时,"Sok“不在名单上。
java.lang.AssertionError:
预期:Pip
实战:Pip,Sok
下面是测试用例:
@RunWith(MockitoJUnitRunner.class)
public class CaptureTest {
@Captor
private ArgumentCaptor<List> listCapture;
@Mock
private ListPrinter listPrinter;
private TestClass testClass;
@Before
public void setUp() {
testClass = new TestClass(listPrinter);
}
@Test
public void testCapture() {
testClass.simulateFailSituation();
verify(listPrinter).printList(listCapture.capture());
// THIS FAILS: Expected:[Pip], Actual:[Pip, Sok]
assertEquals(Collections.singletonList("Pip"), listCapture.getValue());
}
public class TestClass {
private List list = new ArrayList();
private ListPrinter listPrinter;
public TestClass(ListPrinter listPrinter) {
this.listPrinter = listPrinter;
}
private void simulateFailSituation() {
list.add("Pip");
listPrinter.printList(list);
list.add("Sok");
}
}
public interface ListPrinter {
void printList(List list);
}
}
发布于 2017-10-25 16:13:47
这听起来可能是一个令人惊奇的功能,但你可以这样想:如果它在复制,它应该停在哪里?您可能会捕获一些对其他对象有许多引用的对象,最终可能会对JVM实例中的几乎所有对象进行深度复制。
这将是一个严重的表现,所以我有点理解的原因。
因此,您可以从以下两种方法中选择:
doAnswer
方法与Answer<Void>
一起使用,在那里进行测试或复制。顺便说一句,这是新的,请参阅How to make mock to void methods with mockito。我发现它比核实要强大得多。在您的例子中,doAnswer
看起来可能是这样的:
doAnswer(invocation -> {
assertEquals(Collections.singletonList("Pip"), invocation.getArguments()[0]);
return null;
}).when(listPrinter).printList(Matchers.anyList());
发布于 2017-10-25 17:07:59
要同意Vlasec的回答,默认情况下,对Mockito进行深度复制是没有意义的。它无法判断哪些对象是不可变的值对象(如字符串),哪些对象易于复制(ArrayList?),哪些对象绝对不应该被复制(线程?),等等。但是,当方法被调用时,您可以使用一个答案来创建自己的副本。
@Test
public void testCapture() {
// from memory - may need warnings suppressed or different casts/generics
List<String> listSnapshot = new ArrayList<>();
doAnswer(invocation -> {
listSnapshot.addAll((List) invocation.getArguments()[0]);
return null;
}).when(listPrinter).printList(any());
testClass.simulateFailSituation();
listCapture.capture());
assertEquals(Collections.singletonList("Pip"), listSnapshot);
}
尽管Vlasec的更新显示了在一个答案中执行验证的方法,但我更喜欢手动捕获,因为它更接近ArgumentCaptor,更适合于“给定/何时/然后”或“期望/执行/验证”测试格式。此外,在测试系统处于堆栈中时,失败的断言中间测试将导致Mockito失败,这可能导致比测试方法返回后的验证更不明显的失败。
发布于 2017-10-25 16:41:37
处理这件事的一种方法是打电话
doAnswer(invocationOnMock -> {return null;}).when(listPrinter).printList(any());
然后在钩子做自己的捕获与深拷贝,或核实到位。
https://stackoverflow.com/questions/46934599
复制相似问题