Example of Mockito’s argumentCaptor

We Are Going To Discuss About Example of Mockito’s argumentCaptor. So lets Start this Java Article.

Example of Mockito’s argumentCaptor

  1. Example of Mockito's argumentCaptor

    The two main differences are:
    when you capture even a single argument, you are able to make much more elaborate tests on this argument, and with more obvious code;
    an ArgumentCaptor can capture more than once.

  2. Example of Mockito's argumentCaptor

    The two main differences are:
    when you capture even a single argument, you are able to make much more elaborate tests on this argument, and with more obvious code;
    an ArgumentCaptor can capture more than once.

Solution 1

I agree with what @fge said, more over. Lets look at example.
Consider you have a method:

class A {
    public void foo(OtherClass other) {
        SomeData data = new SomeData("Some inner data");
        other.doSomething(data);
    }
}

Now if you want to check the inner data you can use the captor:

// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);

// Run the foo method with the mock
new A().foo(other);

// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());

// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);

Original Author Slava Shpitalny Of This Content

Solution 2

The steps in order to make a full check are :

First, prepare the argument captor :

ArgumentCaptor<ArgumentClass> argumentCaptor = ArgumentCaptor.forClass(ArgumentClass.class);

Second, verify the call to the dependent on component (collaborator of subject under test).

times(1) is the default value, so ne need to add it.

verify(dependentOnComponent, times(1)).method(argumentCaptor.capture());

Third, get the argument passed to collaborator using getValue() of the captor

ArgumentClass someArgument = messageCaptor.getValue();

Fourth, use someArgument for assertions

Original Author Lho Ben Of This Content

Solution 3

The two main differences are:

  • when you capture even a single argument, you are able to make much more elaborate tests on this argument, and with more obvious code;
  • an ArgumentCaptor can capture more than once.

To illustrate the latter, say you have:

final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);

verify(x, times(4)).someMethod(captor.capture()); // for instance

Then the captor will be able to give you access to all 4 arguments, which you can then perform assertions on separately.

This or any number of arguments in fact, since a VerificationMode is not limited to a fixed number of invocations; in any event, the captor will give you access to all of them, if you wish.

This also has the benefit that such tests are (imho) much easier to write than having to implement your own ArgumentMatchers — particularly if you combine mockito with assertj.

Oh, and please consider using TestNG instead of JUnit.

Original Author fge Of This Content

Solution 4

I created this example that simulates a very simple service that uses a repository to save a String (no dependency injection, no entities), just to teach ArgumentCaptor quickly.

  • The service receives, converts to uppercase and trim a name, then invoke the repository.
  • The repository “saves” the String.
  • With ArgumentCaptor I want to know which value is passed to the repository and then check if it’s trimmed and in uppercase, as expected

3 classes: PersonService, PersonRepository and PersonServiceTest (packages omitted)

public class PersonService {

    private PersonRepository personRepository;

    public void setPersonRepository(final PersonRepository personRepository) {
        this.personRepository = personRepository;
    }

    public void savePerson(final String name) {
        this.personRepository.save(name.toUpperCase().trim());
    }

}

public class PersonRepository {

    public void save(final String person) {
        System.out.println(".. saving person ..");
    }
}


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

class PersonServiceTest {

    @Test
    void testPersonService() {

        // Create the repository mock
        final PersonRepository personRepositoryMock = mock(PersonRepository.class);

        // Create the service and set the repository mock
        final PersonService personService = new PersonService();
        personService.setPersonRepository(personRepositoryMock);

        // Save a person
        personService.savePerson("Mario ");

        // Prepare an ArgumentCaptor to capture the value passed to repo.saveMethod
        final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);

        // Capture the argument passed in the unique method invocation
        verify(personRepositoryMock, times(1)).save(captor.capture());

        // Check if the captured value is the expected one
        final String capturedParameter = captor.getValue();
        assertEquals("MARIO", capturedParameter);
    }
}

Original Author MauroB Of This Content

Conclusion

So This is all About This Tutorial. Hope This Tutorial Helped You. Thank You.

Also Read,

Siddharth

I am an Information Technology Engineer. I have Completed my MCA And I have 4 Year Plus Experience, I am a web developer with knowledge of multiple back-end platforms Like PHP, Node.js, Python and frontend JavaScript frameworks Like Angular, React, and Vue.

Leave a Comment