🎓 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
The inOrder() method in Mockito is used to verify that interactions with mock objects occur in a specific sequence. This is particularly useful when the order of method calls is important. This tutorial will demonstrate how to use the inOrder() method in Mockito to verify the sequence 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 OrderService class that has dependencies on InventoryService and PaymentService. Our goal is to test the OrderService methods using the inOrder() method in Mockito to verify the sequence of interactions with InventoryService and PaymentService.
OrderService, InventoryService, and PaymentService Classes
First, create the Order, InventoryService, PaymentService, and OrderService classes.
public class Order {
private String productId;
private int quantity;
private double price;
// Constructor, getters, and setters
public Order(String productId, int quantity, double price) {
this.productId = productId;
this.quantity = quantity;
this.price = price;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
public interface InventoryService {
boolean checkStock(String productId, int quantity);
void reserveProduct(String productId, int quantity);
}
public interface PaymentService {
void processPayment(double amount);
}
public class OrderService {
private final InventoryService inventoryService;
private final PaymentService paymentService;
public OrderService(InventoryService inventoryService, PaymentService paymentService) {
this.inventoryService = inventoryService;
this.paymentService = paymentService;
}
public void placeOrder(Order order) {
if (inventoryService.checkStock(order.getProductId(), order.getQuantity())) {
inventoryService.reserveProduct(order.getProductId(), order.getQuantity());
paymentService.processPayment(order.getPrice() * order.getQuantity());
}
}
}
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.InOrder;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {
@Mock
private InventoryService inventoryService;
@Mock
private PaymentService paymentService;
@InjectMocks
private OrderService orderService;
@Test
public void testPlaceOrder() {
// Given
Order order = new Order("product123", 2, 50.0);
when(inventoryService.checkStock("product123", 2)).thenReturn(true);
// When
orderService.placeOrder(order);
// Then
InOrder inOrder = inOrder(inventoryService, paymentService);
inOrder.verify(inventoryService).checkStock("product123", 2);
inOrder.verify(inventoryService).reserveProduct("product123", 2);
inOrder.verify(paymentService).processPayment(100.0);
}
@Test
public void testPlaceOrderOutOfStock() {
// Given
Order order = new Order("product123", 2, 50.0);
when(inventoryService.checkStock("product123", 2)).thenReturn(false);
// When
orderService.placeOrder(order);
// Then
verify(inventoryService).checkStock("product123", 2);
verify(inventoryService, never()).reserveProduct(anyString(), anyInt());
verify(paymentService, never()).processPayment(anyDouble());
}
}
Explanation
Creating Mocks with
@Mock:- The
@Mockannotation creates mock instances of theInventoryServiceandPaymentServiceinterfaces. These mock instances can be used to simulate the behavior of theInventoryServiceandPaymentServicein a controlled way.
- The
Injecting Mocks with
@InjectMocks:- The
@InjectMocksannotation injects the mockInventoryServiceandPaymentServiceinto theOrderServiceinstance to provide a controlled test environment. This allows theOrderServicemethods to be tested in isolation from the actualInventoryServiceandPaymentServiceimplementations.
- The
Verifying Order of Interactions with
inOrder():- The
InOrder inOrder = inOrder(inventoryService, paymentService);statement creates anInOrderobject to verify the order of interactions with the mock objects. - The
inOrder.verify(inventoryService).checkStock("product123", 2);method checks if thecheckStockmethod was called first on theInventoryServicewith the specified arguments. - The
inOrder.verify(inventoryService).reserveProduct("product123", 2);method checks if thereserveProductmethod was called next on theInventoryServicewith the specified arguments. - The
inOrder.verify(paymentService).processPayment(100.0);method checks if theprocessPaymentmethod was called last on thePaymentServicewith the specified argument.
- The
Verifying No Interactions with
never():- The
verify(inventoryService, never()).reserveProduct(anyString(), anyInt());method checks if thereserveProductmethod was never called on theInventoryServicewhen the product is out of stock. - The
verify(paymentService, never()).processPayment(anyDouble());method checks if theprocessPaymentmethod was never called on thePaymentServicewhen the product is out of stock.
- The
Additional Scenarios
Scenario: Verifying Order of Interactions with Single Mock
In this scenario, we will demonstrate how to verify the order of interactions with a single mock object using the inOrder() method.
@Test
public void testPlaceOrderWithSingleMock() {
// Given
Order order = new Order("product123", 2, 50.0);
when(inventoryService.checkStock("product123", 2)).thenReturn(true);
// When
orderService.placeOrder(order);
// Then
InOrder inOrder = inOrder(inventoryService);
inOrder.verify(inventoryService).checkStock("product123", 2);
inOrder.verify(inventoryService).reserveProduct("product123", 2);
}
Explanation
- Verifying Order of Interactions with Single Mock:
- The
InOrder inOrder = inOrder(inventoryService);statement creates anInOrderobject to verify the order of interactions with the single mock objectinventoryService. - The
inOrder.verify(inventoryService).checkStock("product123", 2);method checks if thecheckStockmethod was called first on theInventoryServicewith the specified arguments. - The
inOrder.verify(inventoryService).reserveProduct("product123", 2);method checks if thereserveProductmethod was called next on theInventoryServicewith the specified arguments.
- The
Conclusion
The inOrder() method in Mockito simplifies the verification of the order of method calls on mock objects for unit testing. By using inOrder(), you can ensure that the code under test interacts with its dependencies in the correct sequence. This step-by-step guide demonstrated how to effectively use the inOrder() method in your unit tests, covering different scenarios to ensure comprehensive testing of the OrderService 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