How to mock constructor in Mockito

Imran Shaikh
0

Creating new objects directly within a method often violates dependency injection principles. Ideally, refactoring to adhere to clean code architecture is the preferred solution.


However, if refactoring isn't immediately feasible, the following example demonstrates how to mock object creation (constructors) in Java using Mockito.


The complete code for this project is available on my GitHub repository (getButton) #text=(GitHub) #icon=(share) #color=(#000000)

Thumbnail image
toc

TransactionService class


The upiPayment() method within my TransactionService class relies on the Account class to check if UPI payments are enabled for a given account number.


To avoid invoking the real isUpiAllowed() method during testing, I intend to mock the Account constructor.


This will allow me to inject a mock Account object that provides a controlled response when its isUpiAllowed() method is called.


This mocking strategy is generally applicable and can be used with other dependencies, such as RestTemplate for mocking API responses.


 public class TransactionService
 {
   public boolean upiPayment(Long accountNumber, BigDecimal amount) {
     Account account = new Account(); // we'll mock this constructor
     boolean upiAllowed = account.isUpiAllowed(accountNumber, amount);
     if (upiAllowed) {
       System.out.println("transaction completed");
       return true;
     }
     return false;
   }
 }

 public class Account {
    public boolean isUpiAllowed(Long accountNumber, BigDecimal amount) {
      System.out.println("Checking is UPI transaction active for account " + accountNumber + " for amount " + amount);
      return Objects.nonNull(accountNumber) && accountNumber > 1
              Objects.nonNull(amount) && amount.compareTo(BigDecimal.valueOf(5000d)) < 0;
   }
 }

Mocking the Account Constructor for JUnit Tests


 @Test
 void upiTransaction() {
   try (MockedConstruction<Account> accountMockedConstruction = Mockito.mockConstruction(Account.class, (mock, context) ->
          Mockito.when(mock.isUpiAllowed(ArgumentMatchers.anyLong(), ArgumentMatchers.any()))
                      .thenReturn(true))) {
     boolean transactionStatus = transactionService.upiPayment(1234567890L, BigDecimal.TEN);
     assertTrue(transactionStatus);
   }
 }

Mockito.mockConstruction() method: Explanation


Mockito's mockConstruction() method provides a powerful way to mock the instantiation of new objects, offering greater flexibility than older approaches like whenNew().


It's particularly useful when dealing with classes you don't directly control, or when you need to mock the creation of objects within the system under test.


This approach allows you to intercept and control the behavior of newly created instances, enabling you to isolate dependencies, simulate specific scenarios, and thoroughly test your code


The following overloaded version of the mockConstructor method is used in this example.


 public static <T> org.mockito.MockedConstruction<T> mockConstruction(java.lang.Class<T> classToMock, org.mockito.MockedConstruction.MockInitializer<T> mockInitializer) { /* compiled code */ }

MockInitializer interface: Explanation


MockInitializer in Mockito is a powerful mechanism that allows you to customize and extend the initialization process of your mocks.


It provides a way to execute specific setup logic before mocks are fully initialized, giving you fine-grained control over their behavior and state.


This is particularly useful for handling complex initialization scenarios, setting up default values, or integrating with other testing frameworks.


To customize our mock, we simply implement the following prepare() method.


 @java.lang.FunctionalInterface
 static interface MockInitializer <T> {
   void prepare(T t, org.mockito.MockedConstruction.Context context) throws java.lang.Throwable;
 }

 static interface Context {
   int getCount();

   java.lang.reflect.Constructor<?> constructor();

   java.util.List<?> arguments();
 }

Conclussion


In this tutorial, we've explored the powerful capabilities of Mockito for mocking constructors, a crucial technique for effective unit testing, especially when dealing with complex dependencies or legacy code.


We've seen how mockConstruction() provides a flexible and modern approach to intercept and control object creation, enabling us to isolate the system under test and simulate various scenarios.


The complete code for this project is available on my GitHub repository (getButton) #text=(GitHub) #icon=(share) #color=(#000000)


Keep learning and keep growing.

Post a Comment

0 Comments
Post a Comment (0)

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Accept !
To Top