0
0
JUnittesting~5 mins

Argument captors in JUnit

Choose your learning style9 modes available
Introduction

Argument captors help you catch and check the values passed to methods during tests. This lets you make sure your code sends the right data to other parts.

You want to check what exact value a method received when called.
You need to verify that a method was called with correct arguments.
You want to test side effects by capturing arguments passed to mocks.
You want to assert on complex objects passed to methods.
You want to debug what data your code sends to collaborators.
Syntax
JUnit
ArgumentCaptor<Type> captor = ArgumentCaptor.forClass(Type.class);
verify(mockObject).methodName(captor.capture());
Type capturedValue = captor.getValue();

Replace Type with the class of the argument you want to capture.

Use captor.getValue() to get the single captured argument or captor.getAllValues() for multiple calls.

Examples
Capture a String argument passed to sendMessage and check it equals "Hello".
JUnit
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(mock).sendMessage(captor.capture());
String message = captor.getValue();
assertEquals("Hello", message);
Capture a User object passed to addUser and check the user's name.
JUnit
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(userService).addUser(captor.capture());
User user = captor.getValue();
assertEquals("Alice", user.getName());
Sample Program

This test checks that when welcomeUser is called with "Bob", the notifyUser method receives the message "Welcome, Bob!".

JUnit
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.mockito.ArgumentCaptor;
import org.junit.jupiter.api.Test;

class NotificationService {
    void notifyUser(String message) {
        // sends notification
    }
}

class UserController {
    private NotificationService notificationService;
    UserController(NotificationService notificationService) {
        this.notificationService = notificationService;
    }
    void welcomeUser(String username) {
        String message = "Welcome, " + username + "!";
        notificationService.notifyUser(message);
    }
}

public class ArgumentCaptorTest {
    @Test
    void testWelcomeUserSendsCorrectMessage() {
        NotificationService mockNotification = mock(NotificationService.class);
        UserController controller = new UserController(mockNotification);

        controller.welcomeUser("Bob");

        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
        verify(mockNotification).notifyUser(captor.capture());

        String capturedMessage = captor.getValue();
        assertEquals("Welcome, Bob!", capturedMessage);
    }
}
OutputSuccess
Important Notes

Argument captors work only with mocks created by Mockito.

Use captor.getAllValues() if the method is called multiple times and you want all arguments.

Always verify the method call before capturing arguments to avoid errors.

Summary

Argument captors let you catch and check method arguments in tests.

They help verify that your code sends the right data to other parts.

Use them with Mockito mocks and verify() calls.