Mockito ArgumentCaptor | Java Fresher Interview
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
ArgumentCaptor is how you grab the actual argument that was passed to a mock so you can inspect it.
It's really useful when the argument is created inside the method you're testing, so you don't have a direct reference to it.
For example, if my service creates a new User object, sets the username and email, and then calls userRepository dot save, I can't just pass that User to verify because I never had a variable for it. That's where ArgumentCaptor comes in. I declare it with the at-Captor annotation, then in my verify statement I pass captor dot capture as the argument.
After that, I call captor dot getValue to extract the actual User that was passed, and now I can assert on its fields like username and email to make sure they were set correctly. The common mistake is using any User dot class when you actually need to check the content. That just verifies the type, not the values inside.
ArgumentCaptor gives you the real object to inspect. If the method was called multiple times, you'd use getAllValues instead of getValue to get a list of all the captured arguments. It's a super common pattern in service layer tests where you're verifying that entities or DTOs were constructed properly before being saved or sent somewhere.
Mockito ArgumentCaptor | Java Fresher Interview
Direct Answer
ArgumentCaptor captures the argument that was passed to a mock method so you can assert on it. Use it when the argument is constructed inside the method under test and you can't compare it directly — like a dynamically created object passed to save().
Code Example
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Captor
private ArgumentCaptor<User> userCaptor; // declare captor for User type
@Test
void shouldCreateUserWithCorrectFields() {
var request = new CreateUserRequest("john.doe", "john@example.com");
userService.createUser(request); // internally creates new User and calls save()
verify(userRepository).save(userCaptor.capture()); // capture the argument
var savedUser = userCaptor.getValue(); // extract the captured User
assertThat(savedUser.getUsername()).isEqualTo("john.doe");
assertThat(savedUser.getEmail()).isEqualTo("john@example.com");
assertThat(savedUser.getCreatedAt()).isNotNull(); // verify timestamp was set
}
}
Common Mistakes & Pitfalls
- Using any() when you need inspection: Freshers often write verify repository dot save any User dot class when they actually need to check field values. That just verifies the type, not the content. Use ArgumentCaptor to capture and inspect the actual object.
- Forgetting getValue(): After calling capture, you must call getValue to extract the captured argument before asserting on it. Freshers sometimes try to assert directly on the captor itself.
- Multiple captures: If the method was called multiple times, getValue returns the last captured value. Use getAllValues to get a list of all captured arguments.
- Overuse in simple cases: If you're just verifying an exact object you already have a reference to, pass it directly to verify — don't use a captor. Use verify mock dot method expectedObject, not capture then compare.
Check your understanding
Answer these without looking back at the article.
- How do you capture arguments from multiple invocations?
- Can you use ArgumentCaptor in stubbing (when)?
- When would a custom Matcher be better than ArgumentCaptor?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.