Mockito argThat Custom Matcher | Java Fresher Interview
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
argThat lets you write custom matching logic when Mockito's built-in matchers aren't expressive enough.
You pass it a predicate—usually a lambda—that takes the argument and returns true if it matches your criteria.
For example, if you're testing a payment service that should only process orders over 100 dollars with PENDING status, you can't use eq because you don't have the exact Order instance, and any is too loose. You write argThat with a lambda: order goes to order dot total over 100 and order dot status equals PENDING. Mockito evaluates this predicate at runtime against the actual argument.
One critical thing freshers forget: always null-check in your predicate. If you write argThat order goes to order dot total over 100 without checking order not equal null, and Mockito tests it against null, you get a NullPointerException and the test blows up. For readability, especially if the logic is complex or reused, extract the predicate to a named method like isHighValueOrder and use argThat with this colon colon isHighValueOrder.
That makes your test read like plain English.
The trade-off is argThat adds complexity—only use it when simpler matchers like eq or anyString won't work. And remember, argThat works the same in both when for stubbing and verify for assertions, just like any other matcher.
Mockito argThat Custom Matcher | Java Fresher Interview
Direct Answer
argThat accepts a custom predicate to match arguments based on domain logic. You pass a lambda or method reference that returns true if the argument meets your criteria. Use it when built-in matchers aren't expressive enough—for example, matching an Order only if its total exceeds 100 and status is PENDING.
Code Example
@ExtendWith(MockitoExtension.class)
class PaymentServiceTest {
@Mock
private PaymentGateway gateway;
@InjectMocks
private PaymentService service;
@Test
void shouldProcessHighValuePendingOrders() {
// Stub: only process orders over $100 with PENDING status
when(gateway.charge(argThat(order ->
order != null &&
order.total() > 100.0 &&
order.status() == OrderStatus.PENDING
))).thenReturn(new PaymentResult(true, "TXN123"));
var order = new Order(1L, "Laptop", 1200.0, OrderStatus.PENDING);
var result = service.processPayment(order);
assertThat(result.success()).isTrue();
// Verify the same custom logic
verify(gateway).charge(argThat(o ->
o != null && o.total() > 100.0 && o.status() == OrderStatus.PENDING
));
}
}
Common Mistakes & Pitfalls
- Null-unsafe predicates: Writing
argThat(order -> order.total() > 100)without checkingorder != nullthrows NullPointerException when Mockito tests the matcher against null. Always add null guards. - Using eq() with missing equals: Testing
verify(repo).save(eq(expectedOrder))fails silently if Order doesn't override equals—Mockito uses identity comparison, not field comparison. Use argThat with field checks instead. - Overly complex predicates: Cramming 10 conditions into one argThat lambda makes tests unreadable and hard to debug when they fail—extract to a named method with a descriptive name like
isEligibleForPremiumShipping.
Check your understanding
Answer these without looking back at the article.
- What is the difference between argThat and eq()?
- How do you use argThat with primitive types?
- How do you write a reusable Mockito matcher?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.