Mockito - nested method invoked multiple times

Viewed 190

I have service class with method which calls ie. repository.save() multiple times. I am testing said service method. Is it possible to capture save() method call on x time and get its passed/returned arguments?

Example:

class MyService{

    void doSomething(){
        myRepository.save(obj1);
        // some code;
        myRepository.save(obj2);
    }

}

I am testing doSomething method and would like to get result and/or passed argument of the first save method. I am using mockito.

2 Answers

Similar to the previous answer, I assume that myRepository is of type MyRepository, is mocked and passed to myService. You can capture and check the arguments passed to the method save() using an ArgumentCaptor:

    @Test
    public void testDoSomething() {

        // Given
        MyRepository myRepository = Mockito.mock(MyRepository.class);
        MyService myService = new MyService(myRepository);

        // When
        myService.doSomething();

        // Then
        ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
        Mockito.verify(myRepository, Mockito.times(2)).save(captor.capture());

        Assert.assertEquals(obj1, captor.getAllValues().get(0)); // First invocation of save()
        Assert.assertEquals(obj2, captor.getAllValues().get(1)); // Second invocation of save()
    }

I assume you pass myRepository as a dependency to MyService. In that case you can create a mock of it in your test and pass that mock instead.

You can call Mockito.doAnswer(...).when(myRepository).save(any()) and pass an Answer that handles the save call of your mocked myRepository. If you need to execute the actual method of the myRepository object, you can add a doCallRealMethod() to the chain.

The argument passed to the Answer is the invocation and you can get the arguments using invocation.getArguments().

Update: @Benoit's answer seems to be a lot more elegant as the ArgumentCaptor doesn't require extra logic to find out if it was the first or second call.

Related