How to mock void methods with Mockito

How to mock void methods with Mockito while writing unit tests in Java?

Some times the method you are unit testing, has a dependency on a method that does not return any value, but has a void return type. To mock such methods we can not use the `when-thenReturn` or `doReturn-when` pattern. 

Our simple expectation from the `Void` dependency method could be that it throws an exception or does not perform any internal action.

Mockito provides two constructs `doThrow-when` and `doNothing-when` to test the above scenarios.


Mockito.doThrow(new Exception()).when(mockObject).methodName();

Mockito.doNothing().when(mockObject).methodName();

Let's look at an example to understand the above two scenarios.

Let's consider our PersonService class and PersonRepository class. We would be writing unit tests for the `delete()` method of PersonService class. The `delete()` method of PersonService class is dependent on `delete()` method of PersonRepository class, which has return type as `void`. PersonRepository is a Spring JPA repository, hence it provides these methods implicitly.

PersonService
public class PersonService {

    private final PersonRepository personRepository;

    public PersonService(PersonRepository personRepository) {
        this.personRepository = personRepository;
    }

    public void delete(Long id) {
        Person person = new Person();
        person.setId(id);
        personRepository.delete(person);
    }
}
  


PersonRepository
public interface PersonRepository extends JpaRepository<Person, Long> {
}
  

The following test class shows how to write unit test to check for success and exception case.

PersonServiceTest
class PersonServiceTest {

    /**
     * Verify successful execution of tested method, by setting dependency method to do nothing.
     */
    @Test
    void create_success() {
        // Create mock of PersonRepository
        PersonRepository mockPersonRepository = Mockito.mock(PersonRepository.class);

        // Create PersonService class and inject mocked PersonRepository object to it.
        PersonService personService = new PersonService(mockPersonRepository);

        // Setup do nothing expectation of PersonRepository
        Mockito.doNothing().when(mockPersonRepository).delete(Mockito.any(Person.class));

        // Call tested method
        personService.delete(34L);

        // Verify that delete() method of PersonRepository was called by the delete() method od PersonService.
        Mockito.verify(mockPersonRepository).delete(Mockito.any(Person.class));
    }

    /**
     * Verify exception is throw by the tested method if dependent method throws exception.
     */
    @Test
    void create_exception() {
        // Create mock of PersonRepository
        PersonRepository mockPersonRepository = Mockito.mock(PersonRepository.class);

        // Create PersonService class and inject mocked PersonRepository object to it.
        PersonService personService = new PersonService(mockPersonRepository);

        // Setup expectation of delete() method of PersonRepository to throw exception
        Mockito.doThrow(new RuntimeException("Invalid Argument")).when(mockPersonRepository).delete(Mockito.any(Person.class));

        // Call tested method, and verify that it throws an exception
        Assertions.assertThrows(RuntimeException.class, () -> personService.delete(100L));
    }
}
  


0 comments:

Post a Comment