valores una tiene sintaxis que parámetros método metodos metodo los llaman llamada declaración crear con clases clase argumentos aparecen java unit-testing mocking mockito

java - una - ¿Puede Mockito capturar argumentos de un método llamado varias veces?



metodos en java netbeans (5)

Con las lambdas de Java 8, una forma conveniente es usar

org.mockito.invocation.InvocationOnMock when(client.deleteByQuery(anyString(), anyString())).then(invocationOnMock -> { assertEquals("myCollection", invocationOnMock.getArgument(0)); assertThat(invocationOnMock.getArgument(1), Matchers.startsWith("id:")); }

Tengo un método al que se llama dos veces y quiero capturar el argumento de la segunda llamada de método.

Esto es lo que he intentado:

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

Pero recibo una excepción TooManyActualInvocations , ya que Mockito piensa que solo se debe llamar a Algo una vez.

¿Cómo puedo verificar el argumento de la segunda convocatoria de doSomething ?


Creo que debería ser

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

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


Desde Mockito 2.0 también existe la posibilidad de usar el método estático Matchers.argThat(ArgumentMatcher) . Con la ayuda de Java 8 ahora es mucho más limpio y más fácil de escribir:

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

Si estás atado a una versión más baja de Java, no hay nada malo:

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

Por supuesto, ninguno de ellos puede verificar el orden de las llamadas, para lo cual debe usar 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")));

Por favor, eche un vistazo al proyecto mockito-java8 que hace posible hacer llamadas como:

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


Si no desea validar todas las llamadas a doSomething() , solo la última, solo puede usar ArgumentCaptor.getValue() . Según el mockito javadoc :

Si el método se llamó varias veces, devuelve el último valor capturado

Así que esto funcionaría (asume que Foo tiene un método 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());


También puede utilizar ArgumentCaptor anotado en @Captor. Por ejemplo:

@Mock List<String> mockedList; @Captor ArgumentCaptor<String> 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)); }