How to Mock Void Methods with Mockito: Everything You Need to Know | Learn Java Skills

Imran Shaikh
0

If you're a programmer, I'm sure you've written about the void method in your application, and as a best practice for writing unit tests of your application using the concepts of test-derived development and behavior-driven development, you might be wondering how we mock the void method.


If so, you've come to the right place. In this brief article, we will learn how to mock the void method in a Java program using mockito, the most popular unit testing framework.


How to Mock Void Methods with Mockito: Everything You Need to Know thumbnail

toc

Why is it necessary to mock the void method?


Let's start with why we need to mock the void method. To make your test case run faster, you should avoid invoking the void function in your unit testing. To accomplish this purpose, we have a doNothing() method.


The mockito's default behavior is to do nothing. You read that accurately. You might be questioning why we need doNothing() in the first place.


The rationale for this is so you may use the ArgumentCaptor to capture the void method's arguments and check that the correct values were supplied to the void method. You may accomplish this by combining doNoting() and the ArgumentCaptor.


You can also throw an exception at the time of invoking the void method to identify the behavior of your program by using the doThrow() method of the mockito.


There are numerous other actions that we can perform by mocking the void method, as we will see in the articles.


How to use the doNothing() method to mock the void method


I'm assuming you have the mockito framework properly configured in your Java application; if not, see what is Mockito post.


doNothing() is the static method of the Mockito class, which is extended by the BDDMockito class.


You may use doNothing() to instruct the void method to do nothing when invoked. The default behavior is to do nothing.


Here's an example of using doNothing with the mockito to mock the void method . In the following example, we limit the DB call by mocking the void method of the saveTransaction() method, which is responsible for storing the transaction data into the DB.


 package in.learnjavaskills.mockitotutorial.service;

 import in.learnjavaskills.mockitotutorial.dto.TransactionDetail;
 import in.learnjavaskills.mockitotutorial.repository.TransactionRepository;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.*;
 import org.mockito.junit.jupiter.MockitoExtension;

 import java.math.BigDecimal;

 @ExtendWith(MockitoExtension.class)
 class TransactionServiceTest
 {
    @Mock
    private TransactionRepository transactionRepository;

	@InjectMocks
    private TransactionService transactionService;

    private long transactionId = 101L;
    private TransactionDetail transactionDetail = new TransactionDetail(transactionId,
            1234_5678_9101_1213L, (byte) 23, (byte) 11, BigDecimal.TEN);

	@Test
    void doNothingWhenSaveTransactionIsInvoked()
    {
        BDDMockito.doNothing()
                .when(transactionRepository)
                .saveTransaction(transactionDetail);

        transactionService.creditCardTransaction(transactionDetail);
    }
 }

How to use the doNothing() method with ArgumentCaptor to capture the arguments of the void method


In our previous example, we saw how we can use the doNothing() method to mock the void method onto doing nothing, and we also learned that doNothing is the default behavior.


As previously explained, we may capture the argument using the ArgumentCaptor by utilizing the doNothing() method.


The mockito class's doNothing() method is used to capture and verify the parameter in the example below.


 package in.learnjavaskills.mockitotutorial.service;

 import in.learnjavaskills.mockitotutorial.dto.TransactionDetail;
 import in.learnjavaskills.mockitotutorial.repository.TransactionRepository;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.*;
 import org.mockito.junit.jupiter.MockitoExtension;

 import java.math.BigDecimal;

 @ExtendWith(MockitoExtension.class)
 class TransactionServiceTest
 {
    @Mock
    private TransactionRepository transactionRepository;

    @InjectMocks
    private TransactionService transactionService;

    private long transactionId = 101L;
    private TransactionDetail transactionDetail = new TransactionDetail(transactionId,
            1234_5678_9101_1213L, (byte) 23, (byte) 11, BigDecimal.TEN);

    @Test
    void argumentCaptorWithDoNothingOnSaveTransaction()
    {
        ArgumentCaptor<TransactionDetail> transactionDetailArgumentCaptor = 
        	ArgumentCaptor.forClass(TransactionDetail.class);

        BDDMockito.doNothing()
                .when(transactionRepository)
                .saveTransaction(transactionDetailArgumentCaptor.capture());

        transactionService.creditCardTransaction(transactionDetail);

        TransactionDetail transactionDetailArgumentCaptorValue = 
        	transactionDetailArgumentCaptor.getValue();
        Assertions.assertThat(transactionDetailArgumentCaptorValue)
        	.isNotNull();
        Assertions.assertThat(transactionDetailArgumentCaptorValue.transactionAmount())
        	.isEqualTo(transactionDetail.transactionAmount());
        Assertions.assertThat(transactionDetailArgumentCaptorValue.transactionId())
        	.isEqualTo(transactionId);
    }
 }

How to use the doThrow() method to throw an exception on the void method


It's best practise to test your code to check how it reacts when exceptions are thrown.


To test how your code behaves, we may utilize the Mockito framework's doThrow() function to throw an exception when methods are invoked.


The doThrow() method of the Mockito class, which is extended by the BDDMockito class, is a static method. When you throw an exception using the doThrow() function, a new exception instance is produced for each method call.


The following is a basic example of utilizing the doThrow() method to throw an exception while using the saveTransaction() method to persist data into the database.


 package in.learnjavaskills.mockitotutorial.service;

 import in.learnjavaskills.mockitotutorial.dto.TransactionDetail;
 import in.learnjavaskills.mockitotutorial.repository.TransactionRepository;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.*;
 import org.mockito.junit.jupiter.MockitoExtension;

 import java.math.BigDecimal;

 @ExtendWith(MockitoExtension.class)
 class TransactionServiceTest
 {
    @Mock
    private TransactionRepository transactionRepository;

    @InjectMocks
    private TransactionService transactionService;

    private long transactionId = 101L;
    private TransactionDetail transactionDetail = new TransactionDetail(transactionId,
            1234_5678_9101_1213L, (byte) 23, (byte) 11, BigDecimal.TEN);

    @Test
    void doThrowWhenSaveTransactionInvoke()
    {
        BDDMockito.doThrow(ClassCastException.class)
                .when(transactionRepository)
                .saveTransaction(transactionDetail);

        Assertions.assertThatThrownBy(()-> transactionService.creditCardTransaction(transactionDetail))
                .isExactlyInstanceOf(ClassCastException.class);
    }
 }

How to use the doCallRealMethod() method to invoke the real implementation of the method


We already know that the Mockito framework's default approach when mocking the void method is to do nothing, but what if we actually want to execute the real implementation to test our code?


In that instance, we may use the doCallRealMethod() function to call the real method.


The following is a simple program for invoking the void method to test the implementation using the doCallRealMethod() function.


 package in.learnjavaskills.mockitotutorial.service;

 import in.learnjavaskills.mockitotutorial.dto.TransactionDetail;
 import in.learnjavaskills.mockitotutorial.repository.TransactionRepository;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.*;
 import org.mockito.junit.jupiter.MockitoExtension;

 import java.math.BigDecimal;

 @ExtendWith(MockitoExtension.class)
 class TransactionServiceTest
 {
    @Mock
    private TransactionRepository transactionRepository;

    @InjectMocks
    private TransactionService transactionService;

    private long transactionId = 101L;
    private TransactionDetail transactionDetail = new TransactionDetail(transactionId,
            1234_5678_9101_1213L, (byte) 23, (byte) 11, BigDecimal.TEN);

    @Test
    void doCallRealMethodWhenSaveTransactionInvoke()
    {
        BDDMockito.doCallRealMethod()
                .when(transactionRepository)
                .saveTransaction(transactionDetail);

        transactionService.creditCardTransaction(transactionDetail);

        BDDMockito.verify(transactionRepository, Mockito.times(1))
                .saveTransaction(transactionDetail);

    }
 }

Conclussion


When it comes to mocking the void method, the mockito framework's default approach is to do nothing. In such scenario, utilize the ArgumentCaptor with doNothing() to capture the void method's parameters and check whether or not the right values were supplied to the void method.


There may be times when you need to test if a void method throws an exception. In this case, doThow() enables us to raise an exception on the void method.


To test the void method's real implementation, we may completely rely on the doCallRealMethod() method, which can partially mock the void method and enable the the method's real implementation.


Keep learning and keep growing.

(getButton) #text=(Next: How to Mock Static Methods with Mockito) #icon=(link) #color=(#2339bd)

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