In a Mockito test, what value comes back when you call a method on a mock that you never stubbed, and what part of Mockito decides that value?
answer
- unstubbed → default answer, not an error
- RETURNS_DEFAULTS = ReturnsEmptyValues
- 0 / false / empty collection / Optional.empty / null
- String returns null, not ""
- strictness ≠ default answer
basics
~10 sThe mock's default answer decides. Mockito's built-in default, Answers.RETURNS_DEFAULTS, gives 0 for numeric primitives, false for boolean, an empty collection, Optional or Stream for those types, and null for every other object. Nothing throws.
solid answer
~50 sEvery Mockito mock carries a **default answer** — a strategy consulted whenever an invocation matches no stubbing. Out of the box that is `Answers.RETURNS_DEFAULTS`, implemented by `ReturnsEmptyValues`: numeric primitives yield `0`, `boolean` yields `false`, `void` does nothing, known collection types yield an empty collection, `Optional` yields `Optional.empty()`, `Stream` yields an empty stream, and everything else — including `String` — yields `null`. The important consequence is that an unstubbed call is *legal*: the mock answers instead of complaining, so a forgotten stub usually surfaces later as a `NullPointerException` deep in the code under test rather than as a Mockito error. Strictness (`STRICT_STUBS`) reports *unused* stubbings and argument mismatches; it does not change what an unstubbed method returns. You can swap the strategy per mock — `mock(Foo.class, Answers.RETURNS_SMART_NULLS)`, `@Mock(answer = ...)`, or `withSettings().defaultAnswer(...)` — including with your own `Answer` implementation.
code
java · 15 linesinterface Repo {
User findById(long id);
List<User> findAll();
Optional<User> findByEmail(String email);
int count();
boolean exists(long id);
}
Repo repo = Mockito.mock(Repo.class);
assertNull(repo.findById(1L));
assertTrue(repo.findAll().isEmpty());
assertTrue(repo.findByEmail("[email protected]").isEmpty());
assertEquals(0, repo.count());
assertFalse(repo.exists(1L));go deeper
Know the value table: 0, false, empty collection/Optional, null for everything else, and that no exception is thrown.
Explain that the value comes from a per-mock Answer (RETURNS_DEFAULTS / ReturnsEmptyValues) and that strictness is a separate concern.
Use it diagnostically — read an NPE inside production code as a probable missing stub — and know how to swap the default per mock.
Have a position on team-wide policy: whether a project-wide custom default answer is worth the hidden coupling, versus explicit stubbing plus strict stubs.
## What a default answer is A Mockito mock is an object whose methods are all intercepted. On each call Mockito looks through the stubbings you registered (`when(...).thenReturn(...)`, `doReturn(...).when(mock).m()`) for one whose method and argument matchers fit the invocation. If one fits, it produces the value. If none fits, Mockito falls back to the mock's **default answer**: an object implementing `org.mockito.stubbing.Answer<Object>` that is asked to produce a value for the invocation. That fallback is a per-mock setting, not a global constant. `Answers` is an enum of ready-made implementations — `RETURNS_DEFAULTS`, `RETURNS_SMART_NULLS`, `RETURNS_MOCKS`, `RETURNS_DEEP_STUBS`, `RETURNS_SELF`, `CALLS_REAL_METHODS` — and every one of them is just an `Answer` you could have written yourself. ## What RETURNS_DEFAULTS actually returns `RETURNS_DEFAULTS` delegates to `ReturnsEmptyValues`: - numeric primitives and their boxes → `0` / `0L` / `0.0` (never `null` for a primitive return, which would be impossible to unbox); - `boolean`/`Boolean` → `false`; - `char` → ``; - `void` → nothing happens; - known collection types (`List`, `Set`, `Map`, `Collection`, `Iterable`, and their common subtypes) → an empty instance, so callers can iterate safely; - `Optional` → `Optional.empty()`, `OptionalInt`/`OptionalLong`/`OptionalDouble` likewise; `Stream` → an empty stream; - everything else, including `String`, arrays, and your own domain types → `null`. The empty-collection and empty-`Optional` behaviour is deliberate: those are the return types where `null` is almost always a bug in the *test*, not a realistic value from the real collaborator. ## Why this matters in practice Because unstubbed calls are legal, the failure mode of a missing stub is displaced. You call `service.handle(cmd)`, the service asks `repository.findById(id)`, gets `null` from the mock, and blows up with an NPE inside the service — a stack trace that points at your production code even though the defect is a missing stub. Recognising that pattern ("NPE on a value that came from a collaborator" = missing stub) is a large part of reading Mockito failures quickly. The same rule explains a common surprise with mocked builders and fluent APIs: `mock.withX().withY()` NPEs on the second call because `withX()` returned `null`, not the mock. That is what `RETURNS_SELF` exists for. ## What does *not* change it Strictness is a separate axis. `Strictness.STRICT_STUBS` (via `MockitoExtension`, `@MockitoSettings`, or `mockitoSession()`) fails the test for stubbings that were never used and for calls that *almost* matched a stubbing with different arguments. It never turns an unstubbed call into an error and never changes the returned value. If you want an unstubbed call to be loud, you supply a default answer that throws, or use `RETURNS_SMART_NULLS` so that *using* the result is loud. Spies are the other side of the coin: a spy created with `Mockito.spy(realObject)` runs the real method when nothing is stubbed, because its default answer is effectively "call the real thing". ## Setting a different default Three equivalent entry points: - annotation: `@Mock(answer = Answers.RETURNS_SMART_NULLS) Repository repo;` - factory overload: `mock(Repository.class, Answers.RETURNS_SMART_NULLS)`; - settings: `mock(Repository.class, withSettings().defaultAnswer(RETURNS_SELF).name("repo"))`, which is the form you need when you also want a name, extra interfaces, or a custom `Answer` lambda. A project-wide default is possible by putting a class named `MockitoConfiguration` implementing `IMockitoConfiguration` on the test classpath and overriding `getDefaultAnswer()`, but it is discouraged: it silently changes the meaning of every mock in the build, including in modules whose authors never read that class.
- A test fails with a NullPointerException inside the class under test, not in the test itself. How does the default-answer rule help you diagnose it?The first thing to check is whether the null came out of a mock. Any collaborator method you did not stub returns null for object types, so the class under test happily receives null and dereferences it. Trace the NPE'd value back to its source: if it originated from a mock call, the fix is a missing stubbing, not defensive code in production.
- Does Strictness.STRICT_STUBS make unstubbed calls fail?No. Strict stubs detect unused stubbings and argument mismatches — a stubbing you registered but never triggered, or a call that hit the same method with different arguments. A call to a method that was never stubbed at all is still answered by the default answer and returns 0/false/empty/null. To make unstubbed calls fail you need a default answer that throws.
- Why does Mockito return an empty list rather than null for a method returning List?Because null is essentially never the useful value there — production code iterates the result, and a null would only produce an NPE that teaches you nothing. Returning an empty collection lets the code under test run to the point where the real assertion fails, which is more informative. The same reasoning gives Optional.empty() and an empty Stream.
saying these in an interview costs you the question
- Claiming an unstubbed method throws an exception by default
- Saying unstubbed String returns an empty string (it returns null)
- Believing STRICT_STUBS makes unstubbed calls fail
- Thinking a mock runs the real method when not stubbed (that is a spy)
- Saying the default answer is global rather than per-mock