Mockito is the most popular mocking framework for Java unit tests. It creates mock objects, stubs method behavior, and verifies interactions.

Setup

  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.8.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>5.8.0</version>
    <scope>test</scope>
</dependency>
  

Creating Mocks

  @ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository repository;

    @InjectMocks
    private UserService userService;

    @Test
    void shouldFindUserById() {
        User user = new User(1L, "Alice");
        when(repository.findById(1L)).thenReturn(Optional.of(user));

        User result = userService.getUser(1L);

        assertEquals("Alice", result.getName());
        verify(repository).findById(1L);
    }
}
  

Manual creation:

  UserRepository repository = mock(UserRepository.class);
UserService service = new UserService(repository);
  

Stubbing

  // Return value
when(repository.findById(1L)).thenReturn(Optional.of(user));

// Throw exception
when(repository.findById(99L)).thenThrow(new UserNotFoundException());

// Multiple calls — sequential returns
when(repository.count())
    .thenReturn(1)
    .thenReturn(2)
    .thenReturn(3);

// Any argument
when(repository.save(any(User.class))).thenAnswer(inv -> inv.getArgument(0));

// Specific argument
when(repository.findByEmail("[email protected]")).thenReturn(Optional.of(user));
  

Argument Matchers

  when(repository.findById(anyLong())).thenReturn(Optional.of(user));
when(repository.findByEmail(eq("[email protected]"))).thenReturn(Optional.of(user));
when(repository.findByName(startsWith("Al"))).thenReturn(List.of(user));

verify(repository).save(argThat(user -> user.getName().equals("Alice")));
verify(repository, never()).delete(any());
verify(repository, times(2)).findAll();
verify(repository, atLeastOnce()).findById(1L);
  

Verifying Interactions

  verify(repository).findById(1L);              // called once (default)
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atMost(5)).findAll();
verifyNoMoreInteractions(repository);
verifyNoInteractions(otherMock);
  

Void Methods

  doNothing().when(repository).deleteById(1L);
doThrow(new RuntimeException()).when(repository).deleteById(99L);

verify(repository).deleteById(1L);
  

Best Practices

  • Mock dependencies, not the class under test
  • Use @InjectMocks to auto-wire mocks into the test subject
  • Prefer when(...).thenReturn(...) over doReturn(...).when(...) unless stubbing void methods
  • Verify behavior that matters — do not over-verify every method call
  • One mock interaction focus per test for clarity