Custom ArgumentMatcher
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
To write a custom argument matcher in Mockito, you implement the ArgumentMatcher interface, which has one method called matches that takes the argument and returns true or false based on your logic.
You pass an instance of your matcher to argThat when you're stubbing or verifying.
For example, if you want to match only orders with an amount greater than a thousand, you'd write argThat of order arrow order dot getAmount greater than one thousand. Since Java 8, you can use a lambda directly like that, which is really concise for simple cases. If your logic is more complex or you're reusing it across tests, create a named class that implements ArgumentMatcher.
The key thing is that your matches method has to handle null arguments safely. Mockito might pass null during the matching process, and if you don't check for it, you'll get a NullPointerException that makes your test fail in a confusing way. So always start your matches method with if argument equals null return false.
Another thing is that matches should be a pure function—don't modify state or call other services inside it, just return true or false based on the argument's properties. You'd use custom matchers for domain-specific rules that built-in matchers can't express, like checking if an email ends with your company domain or if a timestamp is in the future.
For simple stuff like exact equality or type checks, stick with eq or any, they're clearer. But when you need business logic in your matching, custom ArgumentMatcher is the right tool.
Custom ArgumentMatcher
Direct Answer
Implement ArgumentMatcher interface with a matches method that takes the argument and returns true if it matches your criteria. Pass an instance to argThat in stubbing or verification. In Java 8 plus, use a lambda or method reference for conciseness. Always handle null arguments safely in your matches logic to avoid NullPointerException.
Code Example
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private OrderRepository orderRepository;
// Lambda form - concise for simple logic
@Test
void shouldProcessHighValueOrders() {
when(orderRepository.save(argThat(order ->
order != null && order.getAmount() > 1000.0)))
.thenReturn(new Order("processed"));
}
// Class form - reusable, testable, handles null safely
static class ValidOrderMatcher implements ArgumentMatcher<Order> {
@Override
public boolean matches(Order order) {
if (order == null) return false; // Always handle null
return order.getAmount() > 0
&& order.getStatus() != OrderStatus.CANCELLED
&& order.getCustomerId() != null;
}
}
@Test
void shouldSaveOnlyValidOrders() {
verify(orderRepository).save(argThat(new ValidOrderMatcher()));
}
}
Common Mistakes & Pitfalls
- Not handling null in matches(): Freshers write argThat(order -> order.getAmount() > 100) which throws NullPointerException if Mockito passes null during matching—always check if (arg == null) return false first.
- Using side effects in matches(): Writing a matcher that modifies state or prints logs—matches() should be pure and only return true or false based on the argument.
- Overcomplicating simple cases: Writing a custom matcher for something eq() or any() already handles—use built-ins when possible, they're clearer.
- Forgetting to import argThat(): Writing ArgumentMatchers.argThat() without static import makes tests verbose—import static org.mockito.ArgumentMatchers.argThat for cleaner code.
- No descriptive name for class matchers: Calling it CustomMatcher instead of HighValueOrderMatcher—descriptive names make test failures easier to debug.
Check your understanding
Answer these without looking back at the article.
- When would you choose argThat() over ArgumentCaptor?
- How do you reuse a custom ArgumentMatcher across multiple test classes?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.