Skip to main content

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


Comments