What does Mockito's Answers.CALLS_REAL_METHODS do to a mock, and how does the resulting object differ from one created with Mockito.spy(existingInstance)?
answer
- default answer = callRealMethod()
- Objenesis: no constructor, fields null
- spy(instance) copies field state
- spy is a different object than the original
- use doReturn, never when(), on partial mocks
basics
~20 sCALLS_REAL_METHODS makes unstubbed calls run the real implementation on a mock instance created without running any constructor — so its fields are null/zero. spy(instance) wraps an object you constructed, so its state is real. Both need doReturn/doThrow to stub safely.
solid answer
~50 s`mock(Foo.class, Answers.CALLS_REAL_METHODS)` creates a mock whose default answer invokes the real method body instead of returning a default. The object is still instantiated the Mockito way — via Objenesis, **no constructor runs** — so every field is `null`/`0`. Any real method that touches an uninitialised field will NPE. That makes it suitable for abstract classes where you want the concrete template methods to run, or for stateless helpers. `Mockito.spy(realInstance)` is partial mocking of an object you built yourself: Mockito creates the proxy and *copies the fields* of your instance into it, so state and constructor effects are present. `spy(Foo.class)` (the class overload) is closer to `CALLS_REAL_METHODS` — it constructs via the no-arg constructor. In both cases `when(spy.m()).thenReturn(x)` **executes the real `m()`** while stubbing; use `doReturn(x).when(spy).m()`. And neither can intercept `private`, `static` or `final` methods under the subclass mock maker.
code
java · 21 linesabstract class ImportJob {
abstract List<String> fetch();
abstract void store(String item);
int run() {
List<String> items = fetch();
items.forEach(this::store);
return items.size();
}
}
@Test
void runsTemplateForReal() {
ImportJob job = mock(ImportJob.class, Answers.CALLS_REAL_METHODS);
doReturn(List.of("a", "b")).when(job).fetch();
doNothing().when(job).store(anyString());
assertEquals(2, job.run());
verify(job).store("a");
verify(job).store("b");
}go deeper
Know the headline: unstubbed calls run real code, and a spy is a partial mock over a real object.
Add that CALLS_REAL_METHODS skips the constructor so fields are null, and that doReturn is required for stubbing.
Diagnose the failure modes — NPEs from uninitialised state, assertions on the original instance, self-calls into final methods — and say when partial mocking is justified.
Treat the need for partial mocking as a design signal about responsibility split, and set team guidance on where it is tolerated (legacy, third-party, abstract bases).
## The mechanism `Answers.CALLS_REAL_METHODS` is a default answer whose implementation simply calls `invocation.callRealMethod()`. So on a mock created with it, an invocation that matches no stubbing executes the actual bytecode of the class, and one that does match returns the stubbed value. That is *partial mocking*. The crucial detail is how the instance came to exist. Mockito does not call your constructor: it creates the mock instance through Objenesis (a library that allocates an object without running a constructor). Every field therefore holds its JVM default — `null` for references, `0`/`false` for primitives — and any constructor-established invariant is absent. A real method that does `this.repository.find(id)` will throw `NullPointerException`, and the test author sees a confusing failure inside a class they thought they were exercising normally. ## Versus spy(instance) `Mockito.spy(realObject)` also produces a partial mock, but you supply a fully constructed object. Mockito creates its proxy and then **copies the fields** of your instance into the proxy. Consequences: - state is real; constructor logic already ran; - the proxy is a *different object* from the one you passed — self-calls inside the real code go through the proxy (so they are intercepted), but any reference to the original instance held elsewhere is not the spy; - mutations made through the spy do not appear on the original instance you handed in. Asserting on the original after acting on the spy is a classic bug. `Mockito.spy(SomeClass.class)` is the class-taking overload: it constructs an instance using the no-arg constructor and spies on it, which unlike `CALLS_REAL_METHODS` does run initialisation. Rule of thumb: `spy(instance)` when you need real state; `mock(Type.class, CALLS_REAL_METHODS)` when you want real *behaviour* with no state, typically for abstract classes or pure functions. ## The when() trap Both forms share a hazard. `when(partial.compute()).thenReturn(3)` evaluates `partial.compute()` for real before `when` ever sees it — which may throw, mutate state, or hit I/O. The safe form is the `doReturn` family, which never invokes the method: ```java doReturn(3).when(partial).compute(); doThrow(new IllegalStateException()).when(partial).validate(); doNothing().when(partial).flush(); ``` This is the single most-asked follow-up on the topic. ## Abstract classes and template methods The canonical legitimate use is testing an abstract class's concrete logic without writing a test subclass: ```java AbstractJob job = mock(AbstractJob.class, CALLS_REAL_METHODS); doReturn(List.of("a", "b")).when(job).fetchItems(); // the abstract hook job.run(); // real template method ``` Here the absence of constructor state is usually fine, because the class's dependencies are provided through the abstract hooks you stub. ## Limits imposed by the mock maker Partial mocking only intercepts what the active mock maker can intercept. Under the subclass mock maker, `private` and `static` methods, and `final` methods, run their real implementation and cannot be stubbed — including *self-calls* into a final method. The inline mock maker (the default since Mockito 5) removes the final-method restriction; `private` and `static` remain outside ordinary partial mocking. Also, real methods that were never designed for a half-initialised object are precisely where `CALLS_REAL_METHODS` bites. ## Design judgment The Mockito documentation itself flags partial mocks as a code smell in most situations: needing to stub part of a class under test usually signals that the class has two responsibilities and the stubbed part wants to be a collaborator. Legitimate uses cluster around code you cannot restructure — legacy classes, abstract base classes in a framework, and third-party types. In an interview, naming the smell and then giving the narrow legitimate cases is the answer that lands.
- Why must you use doReturn(...).when(spy).method() rather than when(spy.method()).thenReturn(...) on a partial mock?Because when(spy.method()) has to evaluate spy.method() to produce an argument, and on a partial mock that runs the real implementation — which can throw, mutate state or perform I/O before any stubbing is registered. The doReturn form names the method through the proxy without invoking its body, so nothing real executes. It is mandatory whenever the real call is not safe to run.
- You spy on an object, act on the spy, then assert on the original instance and see no changes. Why?spy(instance) does not wrap the original; Mockito creates a separate proxy object and copies the original's fields into it. Everything you do through the spy mutates the proxy's copy, so the original is untouched. Assert on the spy, or restructure the test so only one of the two objects is ever referenced.
- When is CALLS_REAL_METHODS genuinely the right tool?Mainly for abstract classes: you want the concrete template method to run for real while stubbing the abstract hooks, and writing a throwaway subclass adds noise. It also suits stateless utility types whose methods do not touch fields. Anywhere real constructor-established state is needed, spy(instance) is the correct choice instead.
saying these in an interview costs you the question
- Thinking CALLS_REAL_METHODS runs the constructor and initialises fields
- Believing spy(instance) wraps and mutates the original object
- Using when(...).thenReturn(...) on spies without knowing the real method executes
- Claiming final or private methods can be stubbed on a partial mock under the subclass maker
- Treating partial mocks as a normal design tool rather than a last resort