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.