Mockito spy()

1. Overview

Mockito, an esteemed unit testing tool for Java, not only provides ways to mock objects but also to "spy" on real objects. The spy() method allows us to wrap a real object and monitor its interactions, while still calling the real underlying methods unless explicitly stubbed. In this tutorial, we'll delve deep into the spy() method, highlighting its practical applications and benefits.

2. Development Steps

1. Create a new Maven project.

2. Integrate the required dependencies (JUnit 5 and Mockito).

3. Design a class with a method.

4. Formulate a test class for the aforementioned class.

5. Apply the spy() method to create a spy of the real object.

6. Construct and run test cases.

7. Examine the test outcomes.

3. Dependencies (Mockito and JUnit 5)

<!-- JUnit 5 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.10.0</version>
    <scope>test</scope>
</dependency>
<!-- Mockito -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
</dependency>

4. Code Program

// Step 3: Construct the Service class
class Calculator {
    int add(int a, int b) {
        return a + b;
    }
    int multiply(int a, int b) {
        return a * b;
    }
}
// Step 4 and 5: Draft a test class for Calculator
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CalculatorTest {
    @Test
    public void multiplyTestWithSpy() {
        // Create a spy of Calculator using the spy() method
        Calculator calculatorSpy = spy(new Calculator());
        // Stubbing - spy will return specific value for multiply method
        when(calculatorSpy.multiply(5, 2)).thenReturn(15);
        // Execute the methods
        int additionResult = calculatorSpy.add(5, 2); // Calls the real method
        int multiplicationResult = calculatorSpy.multiply(5, 2); // Uses stubbed value
        // Assert the results
        assertEquals(7, additionResult);
        assertEquals(15, multiplicationResult); // Notice the stubbed value
    }
}

Output:

The multiplyTestWithSpy test will pass successfully, showing that while the add method used the real implementation, the multiply method utilized the stubbed value.

Code Explanation:

1. After setting up Mockito and JUnit 5, we introduced a simple Calculator class with methods for addition and multiplication.

2. In our test class, instead of creating a full mock, we created a "spy" on the real Calculator object using the spy() method.

3. With the spy in hand, we selectively stubbed the behavior of the multiply method using the when...thenReturn construct. This means when the multiply method of the spy is called with arguments 5 and 2, it will return the stubbed value (15) instead of the real value (10).

4. We then called both the add and multiply methods on our spy. For the add method, the real implementation was used, resulting in a sum of 7. For the multiply method, our stubbed value was returned, i.e., 15.

5. Lastly, we used assertions to confirm the expected results.

5. Conclusion

The spy() method in Mockito bridges the gap between real objects and mocks. It's a potent tool when we need to retain some real behavior of an object while stubbing out certain parts for isolated testing. By incorporating spies into our unit testing practices, we can obtain fine-grained control over object behaviors, leading to more effective and flexible tests.

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