Using Mockito, will verify(repo).save(anyString()) match a call where the production code passed null? How do you write a matcher that accepts null, or that accepts either null or a String?
answer
- anyString() = any NON-NULL String
- isNull / notNull / nullable(Foo.class)
- any() is the only fully permissive one
- strictness introduced in Mockito 2.1.0
- null actual in 'Argument(s) are different' -> real bug first
basics
~10 sNo. Since Mockito 2.1.0 anyString() and the other typed matchers reject null. Use isNull() to require null, nullable(String.class) to accept null or a String, or any() which matches everything including null.
solid answer
~40 sanyString() means 'any non-null String', so a null argument makes the verification fail with 'Argument(s) are different'. Mockito 2.1.0 tightened this deliberately - in 1.x those matchers matched null and hid real bugs. The null-aware matchers are isNull(), which requires null, notNull(), which requires a non-null value of any type, nullable(String.class), which accepts null or a String, and any(), which accepts anything at all. eq(null) also compiles but isNull() is the readable form and avoids overload ambiguity. The practical rule I follow: if null is a legitimate input in this scenario, say so explicitly with isNull() or nullable(...) so the test documents it; if it is not, leave the strict matcher in place so a null slipping through fails the test rather than being silently accepted.
code
java · 7 linesverify(repo).save(anyString());
verify(audit).log(eq("CREATE"), isNull());
verify(client).call(eq("/orders"), nullable(String.class));
when(repo.findByName(any())).thenReturn(Optional.empty());go deeper
Answer no, and name isNull() and nullable() as the null-aware alternatives.
Explain the Mockito 2.1.0 tightening and pick the right matcher for the intent, including the stub-does-not-match failure mode.
Treat a null actual argument as a production-code lead first, and talk about how loosening matchers to any() erodes the suite.
Frame strict null matching as a policy choice that makes mock-based tests catch a whole defect class, and describe how you would drive the upgrade fallout rather than blanket-relaxing matchers.
## The rule Since Mockito 2.1.0 all the typed convenience matchers exclude null: anyString(), anyList(), anySet(), anyMap(), anyCollection(), anyIterable(), and any(Foo.class). If the code under test passed null, the verification fails and Mockito prints an 'Argument(s) are different!' report with the actual value shown as null. The primitive matchers - anyInt(), anyLong(), anyBoolean() - are unaffected, since a primitive can never be null. ## Why it changed In Mockito 1.x, anyString() matched null and any(Foo.class) ignored its class argument. Tests therefore passed while the code was quietly passing null into a collaborator - one of the most common real defects a mock-based test should catch. The Mockito team made the matchers strict in 2.1.0 to make test harnesses safer, and framed the change as intentional breakage. The upgrade symptom is a suite that starts failing with null actual arguments, and every one of those failures deserves a look at the production code before you loosen the matcher. ## The null-aware matchers - isNull() - matches only null. Generic, so it works for any reference parameter. - notNull() - matches any non-null value, without a type check. - nullable(Foo.class) - matches null or a non-null Foo. This is the matcher for 'this argument is optional'. - any() - matches everything, null included; the loosest option. - eq(null) - legal, and equivalent to isNull(), but it reads worse and with overloaded methods it can force awkward casts. Prefer isNull(). ## Choosing one Think about what the test is claiming. If passing null is a genuine part of this scenario - an optional correlation id that is absent here - write isNull() so the assertion states it. If the argument may or may not be present and the test does not care, nullable(Foo.class) is honest and still keeps a type check. Reaching straight for any() to make a red test green throws away both the null check and the type check, and is the usual way a strict-matcher failure gets papered over. ## Stubbing versus verification The same semantics apply to stubbing. when(repo.findByName(anyString())).thenReturn(Optional.of(user)) will not answer a call made with null; the mock falls back to its default answer instead. That gap typically produces a NullPointerException deep inside the code under test, and the cause is simply that the stub did not match the null argument. When you suspect this, stub with any() temporarily to confirm the argument was null, then decide whether the null itself is the bug. ## Kotlin note In Kotlin, matchers returning null clash with non-nullable parameter types, which is why teams wrap them or use a Kotlin-friendly helper. The semantics are the same; only the null-safety plumbing differs.
- A stub written with when(repo.find(anyString())).thenReturn(user) does not seem to take effect and the code NPEs. What do you check first?Whether the code actually called find(null): anyString() does not match null, so the stub never applies and the mock returns its default of null. Re-stub with any() or isNull() to confirm, then decide whether the null argument is itself the defect rather than just loosening the matcher permanently.
- When would you use nullable(String.class) rather than any()?When null is a legitimate value for that parameter but the type still matters - an optional trace id, for instance. nullable keeps the instanceof check for the non-null case, so a wrongly typed argument still fails, while any() would accept anything at all.
saying these in an interview costs you the question
- Claiming anyString() matches null in current Mockito
- Switching a failing matcher to any() without checking why null arrived
- Thinking isNull() only works for String parameters
- Believing the strictness applies to anyInt() and other primitive matchers
- Using eq(null) and being unable to explain why isNull() is preferred