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