Mockito then Method

The then method in the Mockito framework is used to set a generic answer for a stubbed method. This allows you to define custom behavior for the method when it is called. The method belongs to the OngoingStubbing interface, which is used to configure the behavior of mock methods.

Table of Contents

  1. Introduction
  2. then Method Syntax
  3. Examples
    • Basic Usage
    • Using a Custom Answer
  4. Real-World Use Case
  5. Conclusion

Introduction

Mockito is a popular library in Java for creating and managing mock objects. The then method, which belongs to the OngoingStubbing interface, allows you to set a custom Answer for a stubbed method. This can be useful when you need to define specific behavior for a method, such as returning a dynamic value or performing a side effect.

then Method Syntax

Setting a Generic Answer for a Method

import org.mockito.stubbing.OngoingStubbing;
import org.mockito.stubbing.Answer;

OngoingStubbing<T> then(Answer<?> answer)

Sets a generic answer for the method.

Parameters:

  • answer: The custom Answer to be used for the method.

Returns:

  • An OngoingStubbing object that allows further configuration of the stubbed method.

Examples

Basic Usage

Set a custom answer for a stubbed method.

import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class BasicThenTest {
    @Test
    void testThen() {
        UserService mockUserService = mock(UserService.class);

        // Set a custom answer
        when(mockUserService.getUserDetails(anyString())).then((Answer<String>) invocation -> {
            String userId = invocation.getArgument(0);
            return "User details for " + userId;
        });

        // Call the method
        String details = mockUserService.getUserDetails("123");
        assertEquals("User details for 123", details);
    }
}

class UserService {
    public String getUserDetails(String userId) {
        return "Real user details for " + userId;
    }
}

Using a Custom Answer

Define a custom Answer class and use it with the then method.

import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class CustomAnswerTest {
    @Test
    void testCustomAnswer() {
        UserService mockUserService = mock(UserService.class);

        // Define a custom Answer class
        class CustomAnswer implements Answer<String> {
            @Override
            public String answer(InvocationOnMock invocation) {
                String userId = invocation.getArgument(0);
                return "Custom user details for " + userId;
            }
        }

        // Set the custom answer
        when(mockUserService.getUserDetails(anyString())).then(new CustomAnswer());

        // Call the method
        String details = mockUserService.getUserDetails("456");
        assertEquals("Custom user details for 456", details);
    }
}

class UserService {
    public String getUserDetails(String userId) {
        return "Real user details for " + userId;
    }
}

Real-World Use Case

Using Custom Answers in Service Mocks

In a real-world scenario, you might want to use custom answers to simulate complex behaviors in service methods. This allows you to provide dynamic responses based on the method arguments or simulate side effects.

import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

interface PaymentService {
    String processPayment(String orderId, double amount);
}

class PaymentServiceImpl implements PaymentService {
    public String processPayment(String orderId, double amount) {
        // Real implementation
        return "Payment processed for order " + orderId;
    }
}

public class PaymentServiceTest {
    @Test
    void testProcessPayment() {
        PaymentService mockPaymentService = mock(PaymentService.class);

        // Set a custom answer to simulate payment processing
        when(mockPaymentService.processPayment(anyString(), anyDouble())).then(new Answer<String>() {
            @Override
            public String answer(InvocationOnMock invocation) throws Throwable {
                String orderId = invocation.getArgument(0);
                double amount = invocation.getArgument(1);
                if (amount > 1000) {
                    return "Payment declined for order " + orderId;
                } else {
                    return "Payment processed for order " + orderId;
                }
            }
        });

        // Call the method with different arguments
        String result1 = mockPaymentService.processPayment("123", 500);
        String result2 = mockPaymentService.processPayment("456", 1500);

        // Verify the results
        assertEquals("Payment processed for order 123", result1);
        assertEquals("Payment declined for order 456", result2);
    }
}

In this example, the PaymentServiceTest class uses Mockito’s then method with a custom Answer to simulate different responses based on the payment amount. This allows the test to handle complex behaviors and verify that the service behaves as expected under different conditions.

Conclusion

The then method in Mockito is used for setting custom answers for stubbed methods. By using then, you can define specific behaviors for methods based on their arguments or simulate side effects. This helps ensure that your tests are accurate and comprehensive, allowing you to validate both real and mocked behavior.

Leave a Comment

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

Scroll to Top