Introduction
In this chapter, we will learn about stubbing methods with callbacks using Mockito. Callbacks allow you to define custom behavior for mock methods, enabling more dynamic and flexible stubs. This is particularly useful when the behavior of the method depends on the arguments passed to it.
What is Stubbing?
Stubbing is the process of specifying what mock objects should do when their methods are called. By defining the behavior of mock objects, you can control their interactions and ensure that your tests are reliable and predictable. Stubbing allows you to return specific values, throw exceptions, or execute custom logic when a method is called.
Stubbing with Callbacks
Callbacks allow you to specify custom behavior for stubs, based on the arguments passed to the method or other runtime conditions. This can be useful for testing complex scenarios where the return value of a method depends on the input arguments.
Example: Calculator Class and CalculatorTest Class
Class Under Test: Calculator
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
public double multiply(double a, double b) {
return a * b;
}
public double divide(double a, double b) {
if (b == 0) {
throw new IllegalArgumentException("Division by zero");
}
return a / b;
}
}
Test Class: CalculatorTest
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class CalculatorTest {
@Test
void testStubbingWithCallbacks_Add() {
// Create a mock object of Calculator
Calculator calculator = mock(Calculator.class);
// Stub the add method with a callback
when(calculator.add(anyInt(), anyInt())).thenAnswer(new Answer<Integer>() {
@Override
public Integer answer(InvocationOnMock invocation) {
int a = invocation.getArgument(0);
int b = invocation.getArgument(1);
return a + b;
}
});
// Use the mock object
int result1 = calculator.add(4, 6);
int result2 = calculator.add(7, 3);
// Assert the results
assertEquals(10, result1);
assertEquals(10, result2);
// Verify the interactions
verify(calculator).add(4, 6);
verify(calculator).add(7, 3);
}
}
Explanation
- Creating a Mock:
Calculator calculator = mock(Calculator.class);
This line creates a mock object of the
Calculator
class. - Stubbing with a Callback for Addition:
when(calculator.add(anyInt(), anyInt())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) { int a = invocation.getArgument(0); int b = invocation.getArgument(1); return a + b; } });
This line defines a callback for the
add
method. The callback sums the two arguments and returns the result. - Using the Mock Object for Addition:
int result1 = calculator.add(4, 6); int result2 = calculator.add(7, 3);
These lines call the
add
method on the mock object with different arguments and store the results. - Asserting the Addition Results:
assertEquals(10, result1); assertEquals(10, result2);
These lines check if the results are as expected.
- Verifying Addition Interactions:
verify(calculator).add(4, 6); verify(calculator).add(7, 3);
These lines verify that the
add
method was called with the specified arguments.
Running Test using IntelliJ IDEA
Conclusion
Stubbing methods with callbacks using Mockito allows you to define custom behavior for mock methods based on the arguments passed to them or other runtime conditions. This provides greater flexibility and control over your tests, enabling you to simulate complex scenarios and ensure that your code behaves as expected. By using callbacks, you can create more dynamic and adaptable tests that cover a wider range of cases.