Skip to content

Mockito - examples

Example A

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
  private Long id;
  private String firstName;
  private String lastName;
}
public interface UserRepository {
  Optional<User> findById(Long id);
  User addUser(User user);
}
public interface UserValidator {
  boolean isUserValid(User user);
}
public class UserService {

  private final UserRepository userRepository;
  private final UserValidator userValidator;

  public UserService(final UserRepository userRepository, final UserValidator userValidator) {
    this.userRepository = userRepository;
    this.userValidator = userValidator;
  }

  public User getUserById(final Long id) {
    return userRepository.findById(id).orElseThrow();
  }

  public User createUser(final User user) {
    if (userValidator.isUserValid(user)) {
      return userRepository.addUser(user);
    }
    throw new IllegalArgumentException("User is invalid");
  }
}
@ExtendWith(MockitoExtension.class)
class UserServiceTest {

  private static final long IDENTIFIER = 1L;
  private static final User USER = new User(IDENTIFIER, "Alice", "Cat");

  @Mock
  private UserRepository userRepository;

  @Mock
  private UserValidator userValidator;

  @InjectMocks
  private UserService userService;

  @Test
  void shouldGetUserById() {
    when(userRepository.findById(IDENTIFIER)).thenReturn(Optional.of(USER));

    final User actualUser = userService.getUserById(IDENTIFIER);

    assertThat(actualUser).isEqualTo(USER);
    verify(userRepository).findById(IDENTIFIER);
    verifyNoInteractions(userValidator);
  }

  @Test
  void shouldThrowWhenUserDoesNotExist() {
    when(userRepository.findById(IDENTIFIER)).thenReturn(Optional.empty());

    assertThatExceptionOfType(NoSuchElementException.class)
        .isThrownBy(() -> userService.getUserById(IDENTIFIER));

    verify(userRepository).findById(IDENTIFIER);
    verifyNoInteractions(userValidator);
    verifyNoMoreInteractions(userRepository);
  }

  @Test
  void shouldCreateUser() {
    when(userValidator.isUserValid(USER)).thenReturn(true);
    when(userRepository.addUser(USER)).thenReturn(USER);

    final User actualUser = userService.createUser(USER);

    assertThat(actualUser).isEqualTo(USER);
  }
}

Example B

public interface DatabaseConnection {
  boolean isOpened();
  void open();
  boolean close();
}
public class SdaException extends RuntimeException {
  public SdaException(final String message) {
    super(message);
  }
}
public class DatabaseStore {

  private final List<String> dbData = new ArrayList<>(); // fake database

  private final DatabaseConnection databaseConnection;

  public DatabaseStore(final DatabaseConnection databaseConnection) {
    this.databaseConnection = databaseConnection;
  }

  public int addData(final String data) {
    if (!databaseConnection.isOpened()) {
      databaseConnection.open();
      if (!databaseConnection.isOpened()) {
        throw new SdaException("Unable to open connection to the database");
      }
    }
    dbData.add(data);
    return dbData.size();
  }
}
@ExtendWith(MockitoExtension.class)
class DatabaseStoreTest {

  private static final String ELEMENT = "dbElement";

  @Mock(lenient = true)
  private DatabaseConnection databaseConnection;

  @InjectMocks
  private DatabaseStore databaseStore;

  @Test
  void shouldAddDataForOpenedDatabaseConnection() {
    when(databaseConnection.isOpened()).thenReturn(true);

    final int numberOfData = databaseStore.addData(ELEMENT);

    assertThat(numberOfData).isEqualTo(1);
    verify(databaseConnection).isOpened();
    verify(databaseConnection, never()).open();
  }

  @Test
  void shouldOpenDatabaseConnectionAndAddData() {
    when(databaseConnection.isOpened()).thenReturn(false, true);

    final int numberOfData = databaseStore.addData(ELEMENT);

    assertThat(numberOfData).isEqualTo(1);
    verify(databaseConnection, times(2)).isOpened();
    verify(databaseConnection).open();
    verifyNoMoreInteractions(databaseConnection);
  }

  @Test
  void shouldOpenDatabaseConnectionAndAddDataWithThenAnswer() {
    final int[] executionIndex = { 0 };
    when(databaseConnection.isOpened()).thenAnswer(invocation -> {
      if (executionIndex[0] == 0) {
        executionIndex[0]++;
        return false;
      }
      return true;
    });

    final int numberOfData = databaseStore.addData(ELEMENT);

    assertThat(numberOfData).isEqualTo(1);
    verify(databaseConnection, times(2)).isOpened();
    verify(databaseConnection).open();
    verifyNoMoreInteractions(databaseConnection);
  }
}

Example C

This example is based on the code from [example B] (#example-b). The test shows the use of the doNothing() method.

@ExtendWith(MockitoExtension.class)
class DatabaseStoreTest {

  private static final String ELEMENT = "dbElement";

  @Mock(lenient = true)
  private DatabaseConnection databaseConnection;

  @InjectMocks
  private DatabaseStore databaseStore;

  @Test
  void shouldOpenDatabaseConnectionAndAddData() {
    when(databaseConnection.isOpened()).thenReturn(false, true);
    doNothing().when(databaseConnection).open();
    doReturn(1).when(databaseConnection).isOpened();

    final int numberOfData = databaseStore.addData(ELEMENT);

    assertThat(numberOfData).isEqualTo(1);
    verify(databaseConnection, times(2)).isOpened();
    verify(databaseConnection).open();
    verifyNoMoreInteractions(databaseConnection);
  }
}

Example D

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Message {
  private UUID id;
  private String value;
  private LocalDateTime sendAt;
  private String author;
  private String recipent;
}
public interface MessageSender {
  void send(Message message, MessageType messageType);
}
public enum MessageType {
  PRIVATE, PUBLIC
}
public interface MessageValidator {
  boolean isMessageRecipentReachable(final String recipentId);
  boolean isMessageValid(Message message);
}
public class PrivateMessageSender {

  private final MessageSender messageSender;
  private final MessageValidator messageValidator;

  public PrivateMessageSender(final MessageSender messageSender, final MessageValidator messageValidator) {
    this.messageSender = messageSender;
    this.messageValidator = messageValidator;
  }

  public void sendPrivateMessage(final String text, final String authorId, final String recipentId) {
    final Message message = new Message(UUID.randomUUID(), text, LocalDateTime.now(), authorId, recipentId);
    if (!messageValidator.isMessageValid(message) || !messageValidator.isMessageRecipentReachable(recipentId)) {
      throw new SdaException("Cannot send a private message. Validation has failed");
    }
    messageSender.send(message, MessageType.PRIVATE);
  }
}
@ExtendWith(MockitoExtension.class)
class PrivateMessageSenderTest {

  private static final String TEXT = "Hi Andrew";
  private static final String AUTHOR_ID = "Andrew";
  private static final String RECIPENT_ID = "Alice";

  @Mock
  private MessageSender messageSender;

  @Mock
  private MessageValidator messageValidator;

  @InjectMocks
  private PrivateMessageSender privateMessageSender;

  @Test
  void shouldSendPrivateMessage() {
    when(messageValidator.isMessageValid(any())).thenReturn(true);
    when(messageValidator.isMessageRecipentReachable(anyString())).thenReturn(true);
    doNothing().when(messageSender).send(any(Message.class), eq(MessageType.PRIVATE));

    privateMessageSender.sendPrivateMessage(TEXT, AUTHOR_ID, RECIPENT_ID);

    final InOrder inOrder = Mockito.inOrder(messageValidator);
    inOrder.verify(messageValidator).isMessageValid(any());
    inOrder.verify(messageValidator).isMessageRecipentReachable(anyString());
  }

  @Test
  void shouldThrowWhenRecipentIsInvalid() {
    when(messageValidator.isMessageValid(any())).thenReturn(true);
    when(messageValidator.isMessageRecipentReachable(anyString())).thenReturn(false);

    assertThatExceptionOfType(SdaException.class)
        .isThrownBy(() -> privateMessageSender.sendPrivateMessage(TEXT, AUTHOR_ID, RECIPENT_ID))
        .withNoCause();

    final InOrder inOrder = Mockito.inOrder(messageValidator);
    inOrder.verify(messageValidator).isMessageValid(any());
    inOrder.verify(messageValidator).isMessageRecipentReachable(anyString());
  }
}

Example E

This example is based on the code from [example D] (#example-d). The only difference comes from the test implementation, which in this case uses the @Captor annotation.

@ExtendWith(MockitoExtension.class)
class PrivateMessageSenderTest {

  private static final String TEXT = "Hi Andrew";
  private static final String AUTHOR_ID = "Andrew";
  private static final String RECIPENT_ID = "Alice";

  @Mock
  private MessageSender messageSender;

  @Mock
  private MessageValidator messageValidator;

  @InjectMocks
  private PrivateMessageSender privateMessageSender;

  @Captor
  private ArgumentCaptor<Message> messageCaptor;

  @Test
  void shouldSendPrivateMessage() {
    when(messageValidator.isMessageValid(any())).thenReturn(true);
    when(messageValidator.isMessageRecipentReachable(anyString())).thenReturn(true);
    doNothing().when(messageSender).send(any(Message.class), eq(MessageType.PRIVATE));

    privateMessageSender.sendPrivateMessage(TEXT, AUTHOR_ID, RECIPENT_ID);

    verify(messageValidator).isMessageValid(messageCaptor.capture());
    verify(messageSender).send(messageCaptor.capture(), eq(MessageType.PRIVATE));
    final List<Message> allCapturedValues = messageCaptor.getAllValues();
    assertThat(new HashSet<>(allCapturedValues)).hasSize(1);
    assertMessageContainsExpectedFields(allCapturedValues.get(0));
  }

  private void assertMessageContainsExpectedFields(final Message message) {
    assertThat(message.getAuthor()).isEqualTo(AUTHOR_ID);
    assertThat(message.getRecipent()).isEqualTo(RECIPENT_ID);
    assertThat(message.getValue()).isEqualTo(TEXT);
    assertThat(message.getSendAt()).isNotNull();
    assertThat(message.getId()).isNotNull();
  }

  @Test
  void shouldThrowWhenRecipentIsInvalid() {
    when(messageValidator.isMessageValid(any())).thenReturn(true);
    when(messageValidator.isMessageRecipentReachable(anyString())).thenReturn(false);

    assertThatExceptionOfType(SdaException.class)
        .isThrownBy(() -> privateMessageSender.sendPrivateMessage(TEXT, AUTHOR_ID, RECIPENT_ID))
        .withNoCause();

    verify(messageValidator).isMessageValid(messageCaptor.capture());
    assertMessageContainsExpectedFields(messageCaptor.getValue());
  }
}

Example F

This example is based on the code from example E. The only difference is that it uses methods from the BDDMockito class, which override the when and verify methods.

@ExtendWith(MockitoExtension.class)
class PrivateMessageSenderTest {

  private static final String TEXT = "Hi Andrew";
  private static final String AUTHOR_ID = "Andrew";
  private static final String RECIPENT_ID = "Alice";

  @Mock
  private MessageSender messageSender;

  @Mock
  private MessageValidator messageValidator;

  @InjectMocks
  private PrivateMessageSender privateMessageSender;

  @Captor
  private ArgumentCaptor<Message> messageCaptor;

  @Test
  void shouldSendPrivateMessage() {
    given(messageValidator.isMessageValid(any())).willReturn(true);
    given(messageValidator.isMessageRecipentReachable(anyString())).willReturn(true);
    BDDMockito.doNothing().when(messageSender).send(any(Message.class), eq(MessageType.PRIVATE));

    privateMessageSender.sendPrivateMessage(TEXT, AUTHOR_ID, RECIPENT_ID);

    then(messageValidator).should().isMessageValid(messageCaptor.capture());
    then(messageSender).should().send(messageCaptor.capture(), eq(MessageType.PRIVATE));
    final List<Message> allCapturedValues = messageCaptor.getAllValues();
    assertThat(new HashSet<>(allCapturedValues)).hasSize(1);
    assertMessageContainsExpectedFields(allCapturedValues.get(0));
  }

  private void assertMessageContainsExpectedFields(final Message message) {
    assertThat(message.getAuthor()).isEqualTo(AUTHOR_ID);
    assertThat(message.getRecipent()).isEqualTo(RECIPENT_ID);
    assertThat(message.getValue()).isEqualTo(TEXT);
    assertThat(message.getSendAt()).isNotNull();
    assertThat(message.getId()).isNotNull();
  }

  @Test
  void shouldThrowWhenRecipentIsInvalid() {
    given(messageValidator.isMessageValid(any())).willReturn(true);
    given(messageValidator.isMessageRecipentReachable(anyString())).willReturn(false);

    assertThatExceptionOfType(SdaException.class)
        .isThrownBy(() -> privateMessageSender.sendPrivateMessage(TEXT, AUTHOR_ID, RECIPENT_ID))
        .withNoCause();

    then(messageValidator).should().isMessageValid(messageCaptor.capture());
    assertMessageContainsExpectedFields(messageCaptor.getValue());
  }
}