Introduction
The @InjectMocks
annotation in Mockito is used to automatically inject mock objects into the object being tested. This is particularly useful when the class under test has dependencies that need to be mocked. Instead of manually injecting these mock objects, you can use @InjectMocks
to automatically inject all the mocks marked with @Mock
or @Spy
into the tested object. In this tutorial, we will demonstrate step-by-step how to use the @InjectMocks
annotation in Mockito.
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 an OrderService
class that has a dependency on an OrderRepository
and a NotificationService
. Our goal is to test the OrderService
methods using Mockito to mock the dependencies and inject them using the @InjectMocks
annotation.
OrderService, OrderRepository, and NotificationService Classes
First, create the Order
, OrderRepository
, and NotificationService
classes.
public class Order {
private String orderId;
private String product;
private int quantity;
// Constructor, getters, and setters
}
public interface OrderRepository {
Order findOrderById(String orderId);
void saveOrder(Order order);
}
public class NotificationService {
public void notifyCustomer(String message) {
// Code to notify customer
}
}
Create the OrderService
class that depends on the OrderRepository
and NotificationService
.
public class OrderService {
private final OrderRepository orderRepository;
private final NotificationService notificationService;
public OrderService(OrderRepository orderRepository, NotificationService notificationService) {
this.orderRepository = orderRepository;
this.notificationService = notificationService;
}
public Order getOrder(String orderId) {
return orderRepository.findOrderById(orderId);
}
public void placeOrder(Order order) {
orderRepository.saveOrder(order);
notificationService.notifyCustomer("Order placed: " + order.getOrderId());
}
}
JUnit 5 Test Class with Mockito
Create a test class for OrderService
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 OrderServiceTest {
@Mock
private OrderRepository orderRepository;
@Mock
private NotificationService notificationService;
@InjectMocks
private OrderService orderService;
@Test
public void testGetOrder() {
// Given
Order mockOrder = new Order("1", "Laptop", 1);
when(orderRepository.findOrderById("1")).thenReturn(mockOrder);
// When
Order result = orderService.getOrder("1");
// Then
assertNotNull(result);
assertEquals("1", result.getOrderId());
assertEquals("Laptop", result.getProduct());
assertEquals(1, result.getQuantity());
verify(orderRepository).findOrderById("1");
}
@Test
public void testPlaceOrder() {
// Given
Order newOrder = new Order("2", "Smartphone", 2);
// When
orderService.placeOrder(newOrder);
// Then
verify(orderRepository).saveOrder(newOrder);
verify(notificationService).notifyCustomer("Order placed: 2");
}
}
Explanation
Annotations:
@ExtendWith(MockitoExtension.class)
: Integrates Mockito with JUnit 5, enabling the use of Mockito annotations.@Mock
: Creates mock instances of theOrderRepository
andNotificationService
classes.@InjectMocks
: Injects the mock instances into theOrderService
instance.
Given:
Order mockOrder = new Order("1", "Laptop", 1);
: Creates a mockOrder
object.when(orderRepository.findOrderById("1")).thenReturn(mockOrder);
: Configures the mockOrderRepository
to return the mockOrder
when thefindOrderById
method is called with the argument "1".
When:
Order result = orderService.getOrder("1");
: Calls thegetOrder
method on theOrderService
instance.orderService.placeOrder(newOrder);
: Calls theplaceOrder
method on theOrderService
instance with a newOrder
.
Then:
assertNotNull(result);
: Asserts that the result is not null.assertEquals("1", result.getOrderId());
: Asserts that the order ID of the returnedOrder
is "1".assertEquals("Laptop", result.getProduct());
: Asserts that the product of the returnedOrder
is "Laptop".assertEquals(1, result.getQuantity());
: Asserts that the quantity of the returnedOrder
is 1.verify(orderRepository).findOrderById("1");
: Verifies that thefindOrderById
method was called with the expected argument.verify(orderRepository).saveOrder(newOrder);
: Verifies that thesaveOrder
method was called with the newOrder
.verify(notificationService).notifyCustomer("Order placed: 2");
: Verifies that thenotifyCustomer
method was called with the expected message.
Conclusion
The @InjectMocks
annotation in Mockito simplifies the injection of mock objects into the class under test. By using @Mock
and @InjectMocks
, you can easily set up mock dependencies and focus on testing the behavior of your code. This step-by-step guide demonstrated how to effectively use the @InjectMocks
annotation in your unit tests, covering different scenarios to ensure comprehensive testing of the OrderService
class.
Comments
Post a Comment
Leave Comment