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
@Mock
annotation creates a mock instance of theEmailService
interface. This mock instance can be used to simulate the behavior of theEmailService
in a controlled way.
- The
Injecting Mocks with
@InjectMocks
:- The
@InjectMocks
annotation injects the mockEmailService
into theNotificationService
instance to provide a controlled test environment. This allows theNotificationService
methods to be tested in isolation from the actualEmailService
implementation.
- The
Using BDDMockito:
willDoNothing()
: ThewillDoNothing().given(emailService).sendEmail(any(Email.class));
method configures the mockEmailService
to do nothing when thesendEmail
method is called with anyEmail
object.then()
: Thethen(emailService).should(times(1)).sendEmail(any(Email.class));
method verifies that thesendEmail
method was called on theEmailService
exactly once. This ensures that thesendNotification
method of theNotificationService
class interacts with theEmailService
correctly.- Similarly, the
then(emailService).should(times(times)).sendEmail(any(Email.class));
method verifies that thesendEmail
method was called on theEmailService
the 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 theEmailService
mock object. This ensures that theEmailService
was 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 anInOrder
object to verify the order of interactions with theEmailService
mock 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 thesendEmail
method 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