Mockito Stubbing with Callbacks

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

  1. Creating a Mock:
    Calculator calculator = mock(Calculator.class);
    

    This line creates a mock object of the Calculator class.

  2. 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.

  3. 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.

  4. Asserting the Addition Results:
    assertEquals(10, result1);
    assertEquals(10, result2);
    

    These lines check if the results are as expected.

  5. 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

Mockito Stubbing with Callbacks

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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top