Introduction
The times()
method in Mockito is used to specify the number of times a method should be called on a mock object. This is useful for verifying that certain interactions happened a specific number of times. This tutorial will demonstrate how to use the times()
method in Mockito to check the number of method invocations.
Maven Dependencies
To use Mockito with JUnit 5, add the following dependencies to your pom.xml
file:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Example Scenario
We will create a MessageService
class that has a dependency on a MessageRepository
. Our goal is to test the MessageService
methods using the times()
method in Mockito to check the number of interactions with the MessageRepository
.
MessageService and MessageRepository Classes
First, create the Message
class, the MessageRepository
interface, and the MessageService
class.
public class Message {
private String content;
// Constructor, getters, and setters
public Message(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
public interface MessageRepository {
void saveMessage(Message message);
int getMessageCount();
}
public class MessageService {
private final MessageRepository messageRepository;
public MessageService(MessageRepository messageRepository) {
this.messageRepository = messageRepository;
}
public void sendMessage(String content) {
Message message = new Message(content);
messageRepository.saveMessage(message);
}
public int retrieveMessageCount() {
return messageRepository.getMessageCount();
}
}
JUnit 5 Test Class with Mockito
Create a test class for MessageService
using JUnit 5 and Mockito.
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class MessageServiceTest {
@Mock
private MessageRepository messageRepository;
@InjectMocks
private MessageService messageService;
@Test
public void testSendMessage() {
// Given
String content = "Hello, World!";
// When
messageService.sendMessage(content);
// Then
verify(messageRepository, times(1)).saveMessage(new Message(content));
}
@Test
public void testSendMessageMultipleTimes() {
// Given
String content = "Hello, World!";
// When
messageService.sendMessage(content);
messageService.sendMessage(content);
// Then
verify(messageRepository, times(2)).saveMessage(new Message(content));
}
@Test
public void testRetrieveMessageCount() {
// Given
when(messageRepository.getMessageCount()).thenReturn(5);
// When
int count = messageService.retrieveMessageCount();
// Then
assertEquals(5, count);
verify(messageRepository, times(1)).getMessageCount();
}
}
Explanation
- The
@Mock
annotation creates a mock instance of theMessageRepository
interface. This mock instance can be used to simulate the behavior of theMessageRepository
in a controlled way. - The
@InjectMocks
annotation injects the mockMessageRepository
into theMessageService
instance to provide a controlled test environment. This allows theMessageService
methods to be tested in isolation from the actualMessageRepository
implementation. - The
verify(messageRepository, times(1)).saveMessage(new Message(content));
method checks if thesaveMessage
method was called exactly once on theMessageRepository
with the expectedMessage
object. This ensures that thesendMessage
method of theMessageService
class interacts with theMessageRepository
correctly. - The
verify(messageRepository, times(2)).saveMessage(new Message(content));
method checks if thesaveMessage
method was called exactly twice on theMessageRepository
with the expectedMessage
object. This ensures that thesendMessage
method of theMessageService
class interacts with theMessageRepository
the expected number of times. - The
verify(messageRepository, times(1)).getMessageCount();
method checks if thegetMessageCount
method was called exactly once on theMessageRepository
. This ensures that theretrieveMessageCount
method of theMessageService
class interacts with theMessageRepository
correctly.
Additional Scenarios
Scenario: Verifying No Interactions
In this scenario, we will demonstrate how to verify that no interactions occurred with the mock object using the verifyNoInteractions()
method.
@Test
public void testNoInteractionsWithRepository() {
// Given
// No interactions expected
// When
// No method calls
// Then
verifyNoInteractions(messageRepository);
}
Scenario: Verifying Never Called
In this scenario, we will demonstrate how to verify that a method was never called using the times(0)
method.
@Test
public void testSendMessageNeverCalled() {
// Given
String content = "Hello, World!";
// When
// No sendMessage call
// Then
verify(messageRepository, times(0)).saveMessage(new Message(content));
}
Conclusion
The times()
method in Mockito simplifies the verification of method call counts on mock objects for unit testing. By using times()
, you can easily check if certain methods were called the expected number of times, ensuring that the code under test interacts with its dependencies as expected. This step-by-step guide demonstrated how to effectively use the times()
method in your unit tests, covering different scenarios to ensure comprehensive testing of the MessageService
class.
Related Mockito Methods
Mockito mock()
Mockito spy()
Mockito when()
Mockito thenThrow()
Mockito verify()
Mockito times()
Mockito never()
Mockito any()
Mockito eq()
Mockito inOrder()
Mockito doReturn()
Mockito doThrow()
Mockito doAnswer()
Mockito timeout()
Mockito ArgumentMatchers
Comments
Post a Comment
Leave Comment