Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Mockito capture arguments of a method called multiple times?

I have a method that gets called twice, and I want to capture the argument of the second method call.

Here's what I've tried:

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() 

But I get a TooManyActualInvocations Exception, as Mockito thinks that doSomething should only be called once.

How can I verify the argument of the second call of doSomething?

like image 377
Eric Wilson Avatar asked May 12 '11 16:05

Eric Wilson


People also ask

What is used to return all the captured values in Mockito?

getAllValues. Returns all captured values. Use it when capturing varargs or when the verified method was called multiple times.

Does Mockito verify use equals?

Internally Mockito uses Point class's equals() method to compare object that has been passed to the method as an argument with object configured as expected in verify() method. If equals() is not overridden then java. lang.

What is Mockito argument captor?

Mockito Tutorials Mockito ArgumentCaptor is used to capture arguments for mocked methods. ArgumentCaptor is used with Mockito verify() methods to get the arguments passed when any method is called. This way, we can provide additional JUnit assertions for our tests.


2 Answers

I think it should be

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

Sample from 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()); 
like image 160
proactif Avatar answered Oct 12 '22 18:10

proactif


Since Mockito 2.0 there's also possibility to use static method Matchers.argThat(ArgumentMatcher). With the help of Java 8 it is now much cleaner and more readable to write:

verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("OneSurname"))); verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("AnotherSurname"))); 

If you're tied to lower Java version there's also not-that-bad:

verify(mockBar).doSth(argThat(new ArgumentMatcher<Employee>() {         @Override         public boolean matches(Object emp) {             return ((Employee) emp).getSurname().equals("SomeSurname");         }     })); 

Of course none of those can verify order of calls - for which you should use 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"))); 

Please take a look at mockito-java8 project which makes possible to make calls such as:

verify(mockBar).doSth(assertArg(arg -> assertThat(arg.getSurname()).isEqualTo("Surname"))); 
like image 38
Maciej Dobrowolski Avatar answered Oct 12 '22 18:10

Maciej Dobrowolski