Mockito @InjectMocks Annotation Tutorial

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

  1. Annotations:

    • @ExtendWith(MockitoExtension.class): Integrates Mockito with JUnit 5, enabling the use of Mockito annotations.
    • @Mock: Creates mock instances of the OrderRepository and NotificationService classes.
    • @InjectMocks: Injects the mock instances into the OrderService instance.
  2. Given:

    • Order mockOrder = new Order("1", "Laptop", 1);: Creates a mock Order object.
    • when(orderRepository.findOrderById("1")).thenReturn(mockOrder);: Configures the mock OrderRepository to return the mock Order when the findOrderById method is called with the argument "1".
  3. When:

    • Order result = orderService.getOrder("1");: Calls the getOrder method on the OrderService instance.
    • orderService.placeOrder(newOrder);: Calls the placeOrder method on the OrderService instance with a new Order.
  4. Then:

    • assertNotNull(result);: Asserts that the result is not null.
    • assertEquals("1", result.getOrderId());: Asserts that the order ID of the returned Order is "1".
    • assertEquals("Laptop", result.getProduct());: Asserts that the product of the returned Order is "Laptop".
    • assertEquals(1, result.getQuantity());: Asserts that the quantity of the returned Order is 1.
    • verify(orderRepository).findOrderById("1");: Verifies that the findOrderById method was called with the expected argument.
    • verify(orderRepository).saveOrder(newOrder);: Verifies that the saveOrder method was called with the new Order.
    • verify(notificationService).notifyCustomer("Order placed: 2");: Verifies that the notifyCustomer 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.

Related Mockito Annotations

Comments