Mockito可以捕获多次调用方法的参数吗?

我有一个被调用两次的方法,我想捕获第二个方法调用的参数。

以下是我所尝试的:

ArgumentCaptor<Foo> firstFooCaptor = ArgumentCaptor.forClass(Foo.class); ArgumentCaptor<Foo> secondFooCaptor = ArgumentCaptor.forClass(Foo.class); verify(mockBar).doSomething(firstFooCaptor.capture()); verify(mockBar).doSomething(secondFooCaptor.capture()); // then do some assertions on secondFooCaptor.getValue() 

但是我得到了TooManyActualInvocationsexception,因为Mockito认为doSomething只能被调用一次。

我该如何validationdoSomething的第二个调用的参数?

我认为应该是

 verify(mockBar, times(2)).doSomething(...) 

来自mockito javadoc的示例:

 ArgumentCaptor<Person> peopleCaptor = ArgumentCaptor.forClass(Person.class); verify(mock, times(2)).doSomething(peopleCaptor.capture()); List<Person> capturedPeople = peopleCaptor.getAllValues(); assertEquals("John", capturedPeople.get(0).getName()); assertEquals("Jane", capturedPeople.get(1).getName()); 

如果你不想validation所有对doSomething()的调用,只有最后一个,你可以使用ArgumentCaptor.getValue() 。 根据Mockito javadoc :

如果该方法被多次调用,则返回最新的捕获值

所以这将工作(假设Foo有一个方法getName() ):

 ArgumentCaptor<Foo> 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()); 

由于Mockito 2.0也有可能使用静态方法Matchers.argThat(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<Employee>() { @Override public boolean matches(Object emp) { return ((Employee) emp).getSurname().equals("SomeSurname"); } })); 

当然,这些都不能validation呼叫顺序 – 您应该使用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")));