Core Java

Mockito Spy: Mocking a Method in the Same Class Example

Mockito is a popular testing framework for Java that helps in mocking dependencies. When dealing with unit tests, sometimes we need to mock a method within the same test class instead of an external dependency. This can be achieved using Mockito.spy(). Let us delve into understanding how Mockito spy can be used to mock the same class method in unit testing.

1. Introduction to the Problem

Consider a scenario where a class has multiple methods, and one method calls another within the same class. During unit testing, we might want to mock one method’s behavior while testing another.

01
02
03
04
05
06
07
08
09
10
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
 
    public int calculateSquareSum(int a, int b) {
        int sum = add(a, b);
        return sum * sum;
    }
}

Here, calculateSquareSum() depends on add(). If we want to test calculateSquareSum() independently, we might want to mock add() without modifying the real method.

2. Solution Using Mockito Spy

Mockito provides the spy() method, which allows partial mocking. This means we can call real methods unless explicitly stubbed.

First, add the required dependencies to your pom.xml (for Maven users):

1
2
3
4
5
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>latest__jar__version</version>
</dependency>

Now, let’s write a test case where we mock the add() method.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
 
@ExtendWith(MockitoExtension.class)
public class CalculatorTest {
 
    @Test
    void testCalculateSquareSum() {
        // Create a spy of the Calculator class
        Calculator calculatorSpy = Mockito.spy(new Calculator());
 
        // Mock the add() method to return a fixed value
        when(calculatorSpy.add(2, 3)).thenReturn(10);
 
        // Test calculateSquareSum method
        int result = calculatorSpy.calculateSquareSum(2, 3);
 
        // Verify the expected output
        assertEquals(100, result); // Because (10 * 10) = 100
    }
}

2.1 Code Explanation and Output

In this test case, the CalculatorTest class is used to demonstrate how to mock a method in the same class using Mockito’s spy() method. The class is annotated with @ExtendWith(MockitoExtension.class), which enables Mockito support in JUnit 5 tests.

Inside the testCalculateSquareSum() method, the Calculator class is being tested. A spy object is created using Mockito.spy(), which creates a partial mock of the Calculator class. This allows us to mock specific methods while retaining the real behavior of others.

The add() method of the Calculator class is then mocked using when(calculatorSpy.add(2, 3)).thenReturn(10). This means that, regardless of the actual logic of the add() method, when add(2, 3) is called, it will return 10.

Next, the calculateSquareSum() method is called on the calculatorSpy object with the values 2 and 3. Since the add() method was mocked to return 10, the calculateSquareSum() method computes 10 * 10, which equals 100.

Finally, the result of the method call is verified using assertEquals(100, result), ensuring that the expected value is 100, confirming that the mocking and test logic work as expected.

1
Test passed: Expected 100, got 100.

3. Conclusion

Mockito’s spy() allows us to partially mock a class, making it useful when we need to override specific method behaviors while keeping the rest of the implementation intact. By using when(...).thenReturn(...), we can modify the behavior of a method within the same class, enabling better unit testing for scenarios where one method depends on another.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button