Mockito doAnswer Method

The doAnswer method in Mockito is used to stub a void method with a generic answer. This allows you to specify custom behavior when the void method is called. The Answer interface provides a way to define this behavior by implementing the answer method, which gets invoked when the stubbed method is called.

Table of Contents

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

Introduction

Mockito is a popular library in Java for creating and managing mock objects. The doAnswer method allows you to stub void methods with custom behavior, which can be useful for more complex testing scenarios where simple stubbing with doNothing, doThrow, or doReturn is not sufficient.

doAnswer Method Syntax

Stubbing a Void Method with a Generic Answer

static Stubber doAnswer(Answer answer)

Sets custom behavior for a void method when it is called.

Parameters:

  • answer: An implementation of the Answer interface, defining the custom behavior to execute when the method is called.

Returns:

  • A Stubber object that allows further stubbing configurations.

Examples

Basic Usage

Stub a void method with a simple custom answer.

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import org.mockito.stubbing.Answer;
import org.junit.jupiter.api.Test;

public class BasicDoAnswerTest {
    @Test
    void testDoAnswer() {
        UserService mockUserService = mock(UserService.class);

        // Stub the deleteUser method with a custom answer
        doAnswer((Answer<Void>) invocation -> {
            String userId = invocation.getArgument(0);
            System.out.println("User " + userId + " deleted");
            return null;
        }).when(mockUserService).deleteUser("123");

        // Call the method
        mockUserService.deleteUser("123");

        // Verify that the method was called
        verify(mockUserService).deleteUser("123");
    }
}

class UserService {
    public void deleteUser(String userId) {
        // Method implementation
    }
}

Custom Answer Logic

Stub a void method with more complex custom logic using the Answer interface.

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import org.mockito.stubbing.Answer;
import org.junit.jupiter.api.Test;

public class CustomDoAnswerTest {
    @Test
    void testDoAnswerWithCustomLogic() {
        UserService mockUserService = mock(UserService.class);

        // Stub the deleteUser method with custom logic
        doAnswer((Answer<Void>) invocation -> {
            String userId = invocation.getArgument(0);
            if ("admin".equals(userId)) {
                throw new IllegalArgumentException("Cannot delete admin user");
            }
            System.out.println("User " + userId + " deleted");
            return null;
        }).when(mockUserService).deleteUser("admin");

        // Call the method and expect an exception
        assertThrows(IllegalArgumentException.class, () -> mockUserService.deleteUser("admin"));

        // Verify that the method was called
        verify(mockUserService).deleteUser("admin");
    }
}

class UserService {
    public void deleteUser(String userId) {
        // Method implementation
    }
}

Real-World Use Case

Testing a Service Method with Complex Dependencies

In a real-world scenario, you might have a service class that calls a void method on a dependency. Using doAnswer, you can configure the void method to execute custom logic during your test.

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import org.mockito.stubbing.Answer;
import org.junit.jupiter.api.Test;

interface NotificationService {
    void sendNotification(String message);
}

class UserService {
    private final NotificationService notificationService;

    public UserService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void deleteUser(String userId) {
        // Perform user deletion logic
        notificationService.sendNotification("User " + userId + " deleted");
    }
}

public class UserServiceTest {
    @Test
    void testDeleteUserWithCustomNotification() {
        NotificationService mockNotificationService = mock(NotificationService.class);
        UserService userService = new UserService(mockNotificationService);

        // Stub the sendNotification method with custom logic
        doAnswer((Answer<Void>) invocation -> {
            String message = invocation.getArgument(0);
            System.out.println("Sending notification: " + message);
            return null;
        }).when(mockNotificationService).sendNotification("User 123 deleted");

        // Call the deleteUser method
        userService.deleteUser("123");

        // Verify that the sendNotification method was called
        verify(mockNotificationService).sendNotification("User 123 deleted");
    }
}

In this example, the UserServiceTest class uses Mockito’s doAnswer method to configure the sendNotification method of the NotificationService interface to execute custom logic when called. The test verifies that the sendNotification method is called with the expected message during the execution of the deleteUser method in the UserService class.

Conclusion

The doAnswer method in Mockito is used for stubbing void methods with custom behavior. By using doAnswer and implementing the Answer interface, you can define complex logic to be executed when void methods are called. This allows you to create flexible and comprehensive tests for your Java applications.

Leave a Comment

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

Scroll to Top