我有一个方法被调用两次,我想捕获第二个方法调用的参数。
以下是我的尝试:
ArgumentCaptor firstFooCaptor = ArgumentCaptor.forClass(Foo.class);
ArgumentCaptor secondFooCaptor = ArgumentCaptor.forClass(Foo.class);
verify(mockBar).doSomething(firstFooCaptor.capture());
verify(mockBar).doSomething(secondFooCaptor.capture());
// then do some assertions on secondFooCaptor.getValue()
但我得到了一个TooManyActualInvocations例外,因为mockito认为doSomething只应该调用一次。
如何验证doSomething第二次调用的参数?
我想应该是
verify(mockBar, times(2)).doSomething(...)
Mockito Javadoc的样品:
ArgumentCaptor peopleCaptor = ArgumentCaptor.forClass(Person.class);
verify(mock, times(2)).doSomething(peopleCaptor.capture());
List capturedPeople = peopleCaptor.getAllValues();
assertEquals("John", capturedPeople.get(0).getName());
assertEquals("Jane", capturedPeople.get(1).getName());
你能在每次单独的调用中捕获传递给doSomething()的参数吗?
我喜欢stackoverflow.com/a/14890172
应该注意的是,如果你这样做:Person person = new Person("John"); doSomething(person); person.setName("Jane"); doSomething(person);捕获的论点将是相同的两次(因为实际上它是同一个人的对象),所以capturedPeople.get(0).getName() == capturedPeople.get(1).getName() =="Jane"也可以参见groups.google.com/forum/!msg/mockito/kbrocvedyt0/5htarml9r2‌&8203;wj.
这很好,但是我如何测试两个不同类型的对象调用呢?例如,executorService.submit(new myUnableImpl());然后是executorService.submit(new myAnotherRunableImpl())?
如果有人需要处理@asmaier描述的案例,我在这里发布了一个答案:stackoverflow.com/a/36574817/1466267
嗨@leon,你得到不同类型参数的解决方案了吗?
对于仍然对Leon问题的答案感到疑惑的人,您可以使用公共基类(Runnable),如果需要,可以对捕获的参数进行更具体的类型检查。
由于mockito 2.0,还可以使用静态方法matchers.arghat(argumentmatcher)。在Java 8的帮助下,它现在变得更干净,更易于阅读:
verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("OneSurname")));
verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("AnotherSurname")));
如果你被绑定到较低的Java版本,也没有那么糟糕:
verify(mockBar).doSth(argThat(new ArgumentMatcher() {
@Override
public boolean matches(Object emp) {
return ((Employee) emp).getSurname().equals("SomeSurname");
}
}));
当然,这些都不能验证通话顺序—您应该使用inorder:
InOrder inOrder = inOrder(mockBar);
inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("FirstSurname")));
inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("SecondSurname")));
请看一下mockito-java8项目,它可以进行如下调用:
verify(mockBar).doSth(assertArg(arg -> assertThat(arg.getSurname()).isEqualTo("Surname")));
这是一个很好的技巧。不过,我现在得到了一些相当神秘的输出:"想要但没有调用:/n mockappender.append();"—arg有一个CharSequence。你知道如何让报告正确打印出"通缉犯"参数吗?
如果您不想验证所有对doSomething()的调用,只验证最后一个调用,则可以使用ArgumentCaptor.getValue()。根据Mockito Javadoc:
如果多次调用该方法,则返回最新捕获的值
所以这是可行的(假设Foo有一个方法getName()):
ArgumentCaptor fooCaptor = ArgumentCaptor.forClass(Foo.class);
verify(mockBar, times(2)).doSomething(fooCaptor.capture());
//getValue() contains value set in second call to doSomething()
assertEquals("2nd one", fooCaptor.getValue().getName());
是否有任何方法可以捕获这两个值?
@哈什用了Listfoos = fooCaptor.getValues();。
也可以使用@captor注释的argumentcaptor。例如:
@Mock
List mockedList;
@Captor
ArgumentCaptor argCaptor;
@BeforeTest
public void init() {
//Initialize objects annotated with @Mock, @Captor and @Spy.
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldCallAddMethodTwice() {
mockedList.add("one");
mockedList.add("two");
Mockito.verify(mockedList, times(2)).add(argCaptor.capture());
assertEquals("one", argCaptor.getAllValues().get(0));
assertEquals("two", argCaptor.getAllValues().get(1));
}
用Java 8的lambdas,一个方便的方法就是使用
org.mockito.invocation.InvocationOnMock
when(client.deleteByQuery(anyString(), anyString())).then(invocationOnMock -> {
assertEquals("myCollection", invocationOnMock.getArgument(0));
assertThat(invocationOnMock.getArgument(1), Matchers.startsWith("id:"));
}
我看不出这比旧方法更方便。我喜欢使用羊羔肉,但我不确定这是不是。