Mockito peut-il capturer des arguments d’une méthode appelée plusieurs fois?

J’ai une méthode qui est appelée deux fois et je veux capturer l’argument du deuxième appel de méthode.

Voici ce que j’ai essayé:

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

Mais je reçois une exception TooManyActualInvocations , car Mockito pense que doSomething ne doit être appelé qu’une seule fois.

Comment puis-je vérifier l’argument du deuxième appel de doSomething ?

Je pense que ça devrait être

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

Exemple de 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()); 

Depuis Mockito 2.0, il est également possible d’utiliser la méthode statique Matchers.argThat (ArgumentMatcher) . Avec l’aide de Java 8, il est maintenant beaucoup plus propre et plus lisible d’écrire:

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

Si vous êtes lié à la version Java inférieure, il n’y a pas que ça:

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

Bien sûr, aucun de ceux-ci ne peut vérifier l’ordre des appels – pour lequel vous devez utiliser 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"))); 

S’il vous plaît jeter un oeil à mockito-java8 projet qui permet de faire des appels tels que:

 verify(mockBar).doSth(assertArg(arg -> assertThat(arg.getSurname()).isEqualTo("Surname"))); 

Si vous ne voulez pas valider tous les appels à doSomething() , seulement le dernier, vous pouvez simplement utiliser ArgumentCaptor.getValue() . Selon le Mockito javadoc :

Si la méthode a été appelée plusieurs fois, elle renvoie la dernière valeur capturée

Donc cela fonctionnerait (suppose que Foo a une méthode 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()); 

Vous pouvez également utiliser l’argumentCaptor annoté @Captor. Par exemple:

 @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)); }