🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Introduction
BDDMockito.times() is a method provided by Mockito to support the Behavior-Driven Development (BDD) style of writing tests. It is used to verify the number of times a method was called on a mock object. This is particularly useful when you want to ensure that a method is called a specific number of times. This tutorial will demonstrate how to use BDDMockito.times() to verify the number of method calls in a BDD style.
Maven Dependencies
To use Mockito with JUnit 5 and enable BDDMockito syntax, 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 NotificationService class that has a dependency on an EmailService. Our goal is to test the NotificationService methods using BDDMockito.times() to verify the number of method calls.
NotificationService and EmailService Classes
First, create the Email class, the EmailService interface, and the NotificationService class.
public class Email {
private String recipient;
private String message;
// Constructor, getters, and setters
public Email(String recipient, String message) {
this.recipient = recipient;
this.message = message;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
public interface EmailService {
void sendEmail(Email email);
}
public class NotificationService {
private final EmailService emailService;
public NotificationService(EmailService emailService) {
this.emailService = emailService;
}
public void sendNotification(String recipient, String message) {
Email email = new Email(recipient, message);
emailService.sendEmail(email);
}
public void sendMultipleNotifications(String recipient, String message, int times) {
for (int i = 0; i < times; i++) {
sendNotification(recipient, message);
}
}
}
JUnit 5 Test Class with BDDMockito
Create a test class for NotificationService using JUnit 5 and BDDMockito.
import static org.mockito.BDDMockito.*;
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 NotificationServiceTest {
@Mock
private EmailService emailService;
@InjectMocks
private NotificationService notificationService;
@Test
public void testSendNotification() {
// Given
String recipient = "test@example.com";
String message = "Hello, World!";
willDoNothing().given(emailService).sendEmail(any(Email.class));
// When
notificationService.sendNotification(recipient, message);
// Then
then(emailService).should(times(1)).sendEmail(any(Email.class));
}
@Test
public void testSendMultipleNotifications() {
// Given
String recipient = "test@example.com";
String message = "Hello, World!";
int times = 3;
willDoNothing().given(emailService).sendEmail(any(Email.class));
// When
notificationService.sendMultipleNotifications(recipient, message, times);
// Then
then(emailService).should(times(times)).sendEmail(any(Email.class));
}
}
Explanation
Creating Mocks with
@Mock:- The
@Mockannotation creates a mock instance of theEmailServiceinterface. This mock instance can be used to simulate the behavior of theEmailServicein a controlled way.
- The
Injecting Mocks with
@InjectMocks:- The
@InjectMocksannotation injects the mockEmailServiceinto theNotificationServiceinstance to provide a controlled test environment. This allows theNotificationServicemethods to be tested in isolation from the actualEmailServiceimplementation.
- The
Using BDDMockito:
willDoNothing(): ThewillDoNothing().given(emailService).sendEmail(any(Email.class));method configures the mockEmailServiceto do nothing when thesendEmailmethod is called with anyEmailobject.then(): Thethen(emailService).should(times(1)).sendEmail(any(Email.class));method verifies that thesendEmailmethod was called on theEmailServiceexactly once. This ensures that thesendNotificationmethod of theNotificationServiceclass interacts with theEmailServicecorrectly.- Similarly, the
then(emailService).should(times(times)).sendEmail(any(Email.class));method verifies that thesendEmailmethod was called on theEmailServicethe specified number of times.
Additional Scenarios
Scenario: Verifying No Interactions
In this scenario, we will demonstrate how to verify that no interactions occurred with the mock object using BDDMockito.
@Test
public void testNoInteractionsWithEmailService() {
// Given
// No interactions expected
// When
// No method calls
// Then
then(emailService).shouldHaveNoInteractions();
}
Explanation
- Verifying No Interactions:
- The
then(emailService).shouldHaveNoInteractions();method verifies that no interactions occurred with theEmailServicemock object. This ensures that theEmailServicewas not used during the test.
- The
Scenario: Verifying Method Call Order
In this scenario, we will demonstrate how to verify the order of method calls using BDDMockito.
@Test
public void testMethodCallOrder() {
// Given
String recipient = "test@example.com";
String message1 = "Hello, World!";
String message2 = "Goodbye, World!";
willDoNothing().given(emailService).sendEmail(any(Email.class));
// When
notificationService.sendNotification(recipient, message1);
notificationService.sendNotification(recipient, message2);
// Then
InOrder inOrder = inOrder(emailService);
then(emailService).should(inOrder).sendEmail(argThat(email -> email.getMessage().equals("Hello, World!")));
then(emailService).should(inOrder).sendEmail(argThat(email -> email.getMessage().equals("Goodbye, World!")));
}
Explanation
- Verifying Method Call Order:
- The
InOrder inOrder = inOrder(emailService);statement creates anInOrderobject to verify the order of interactions with theEmailServicemock object. - The
then(emailService).should(inOrder).sendEmail(argThat(email -> email.getMessage().equals("Hello, World!")));andthen(emailService).should(inOrder).sendEmail(argThat(email -> email.getMessage().equals("Goodbye, World!")));methods verify that thesendEmailmethod was called with the specified messages in the correct order on theEmailService.
- The
Conclusion
Using BDDMockito.times() in Mockito allows you to write more readable and expressive tests that follow the Behavior-Driven Development (BDD) style. By using times() for verifying the number of method calls, you can handle various scenarios and control the interactions with mock objects. This step-by-step guide demonstrated how to effectively use BDDMockito.times() in your unit tests, covering different scenarios to ensure comprehensive testing of the NotificationService class.
Related Mockito BDDMockito Class Methods (Behavior-Driven Development Style)
Mockito BDDMockito
Mockito BDDMockito given()
Mockito BDDMockito willThrow()
Mockito BDDMockito willAnswer()
Mockito BDDMockito willReturn()
Mockito BDDMockito willDoNothing()
Mockito BDDMockito willCallRealMethod()
Mockito BDDMockito then()
Mockito BDDMockito.any()
Mockito BDDMockito.times()
Comments
Post a Comment
Leave Comment