Mocking a fluent builder in Mockito usually breaks with a NullPointerException on the second chained call. Why, and how does the Answers.RETURNS_SELF default answer fix it?
answer
- builder link returns null → NPE on next call
- RETURNS_SELF = ReturnsSelf answer
- return type assignable from mock type → return mock
- terminal build() still returns default
- prefer the real builder when it is yours
basics
~20 sEach unstubbed builder method returns null by default, so the next call in the chain dereferences null. RETURNS_SELF makes an unstubbed method return the mock itself whenever the return type is assignable from the mock's type, keeping the chain alive.
solid answer
~50 sA fluent builder works because every `withX()` returns `this`. A mock knows nothing about that contract: with the standard default answer each unstubbed builder method returns `null`, so `builder.name("x").age(3)` NPEs on `age`. `Answers.RETURNS_SELF` (implemented by `ReturnsSelf`) fixes it: for an unstubbed call it checks whether the method's return type is assignable from the mocked type, and if so returns the mock instance itself; otherwise it delegates to `RETURNS_DEFAULTS`. So the chain of `Builder`-returning methods flows through the same mock, and the terminal `build()` — which returns a different type — still returns a normal default you can stub explicitly. Set it with `@Mock(answer = Answers.RETURNS_SELF)` or `mock(Builder.class, withSettings().defaultAnswer(RETURNS_SELF))`. Worth saying out loud in an interview: mocking your own builder is usually a smell — just use the real builder. `RETURNS_SELF` earns its keep for third-party fluent clients you cannot construct cheaply.
code
java · 16 lines@Mock(answer = Answers.RETURNS_SELF)
RequestBuilder builder;
@Test
void configuresRequest() {
Request expected = new Request("/orders");
when(builder.build()).thenReturn(expected); // terminal call still needs a stub
Request actual = builder.path("/orders")
.header("Accept", "application/json")
.timeout(Duration.ofSeconds(5))
.build();
assertSame(expected, actual);
verify(builder).header("Accept", "application/json");
}go deeper
Explain the NPE cause — unstubbed links return null — and that RETURNS_SELF returns the mock so chaining works.
Give the assignability rule and note that the terminal method still falls back to normal defaults.
Contrast with per-link stubbing and deep stubs, and say when mocking a fluent type is justified at all.
Frame it as a test-design question: which third-party fluent surfaces are worth mocking versus wrapping behind your own narrow port.
## Why chained calls break on a mock A fluent API is a convention, not a language feature: each configuring method happens to `return this`. When you mock the type, none of that implementation exists. Every method is intercepted, and an unstubbed one is answered by the mock's default answer, which for object return types is `null`. So the first call in the chain returns `null`, and the second call is invoked on `null` — a `NullPointerException` at the second link, with a message that looks nothing like "you mocked a builder". The manual workaround is to stub each link back to the mock: `when(builder.name(any())).thenReturn(builder);` repeated per method, which is noisy and needs updating whenever the builder gains a method. ## What RETURNS_SELF does `Answers.RETURNS_SELF` supplies `ReturnsSelf` as the default answer. On an unstubbed invocation it asks a simple question: *is the invoked method's declared return type assignable from the type of this mock?* If yes, it returns the mock itself. If no, it delegates to `ReturnsEmptyValues` — the ordinary `RETURNS_DEFAULTS` behaviour. That assignability rule is what makes it well behaved in practice: - `Builder name(String)` returns the mock → the chain continues; - `Builder self()` on a supertype return, e.g. `AbstractBuilder`, still returns the mock, because the mocked type is assignable to it; - `Product build()` returns the ordinary default (`null`), because `Product` is not a supertype of the builder — so you stub the terminal call explicitly, which is exactly the value your test cares about. Generics with self types (`B extends Builder<B>`) work at runtime because erasure leaves the raw supertype, which is still assignable. ## How to configure it ```java @Mock(answer = Answers.RETURNS_SELF) HttpRequestBuilder request; ``` or imperatively: ```java HttpRequestBuilder request = mock(HttpRequestBuilder.class, Answers.RETURNS_SELF); // or, when other settings are needed: mock(HttpRequestBuilder.class, withSettings().defaultAnswer(RETURNS_SELF).name("request")); ``` Verification works normally afterwards — `verify(request).timeout(Duration.ofSeconds(5))` — and because every link is the *same* mock instance, all the chained calls are recorded on one invocation container, which also means `verify(request, times(3))` counts across the whole chain if you use the same method. ## When to use it, and when not to The honest answer in an interview includes the design caveat. If the builder is *your* class, mocking it is usually wrong: builders are cheap, deterministic, dependency-free value constructors, and using the real one produces a stronger test with no stubbing at all. Reach for `RETURNS_SELF` when the fluent type belongs to someone else and is expensive or awkward to instantiate — an HTTP client request builder, a cloud SDK request builder, a query DSL — and when what you actually want to assert is *which configuration calls were made*. Two comparisons interviewers like to draw: - **versus stubbing each link**: same effect, far less code, and it survives new methods on the builder. - **versus deep stubs**: deep stubs return a fresh mock of each return type and remember it so chains through *different* types work; `RETURNS_SELF` returns the same mock and only for self-returning methods. For a genuine builder, `RETURNS_SELF` is the narrower, more honest tool — the chain really is one object at runtime. A final gotcha: if the builder's terminal method returns a type the test then uses, remember it is still `null` unless stubbed. `RETURNS_SELF` deliberately does not auto-mock it.
- With RETURNS_SELF, what does the builder's terminal build() method return?Whatever RETURNS_DEFAULTS would give — normally null, since the built product type is not assignable from the builder type. That is intentional: the product is the value your test cares about, so you stub it explicitly with when(builder.build()).thenReturn(product). Only self-returning methods are short-circuited to the mock.
- Why is mocking your own builder often a smell?Builders are usually pure, cheap, side-effect-free object constructors with no I/O and no collaborators, so the real one runs fine inside a unit test and gives you a real product object to assert on. Mocking it replaces a trustworthy implementation with an assumption about it, and couples the test to the builder's method sequence rather than to the resulting value. Reserve mocking for fluent types you do not own or cannot instantiate cheaply.
saying these in an interview costs you the question
- Saying RETURNS_SELF makes every unstubbed method return the mock, regardless of return type
- Expecting build() to return a non-null product automatically
- Confusing it with deep stubs
- Claiming you must stub each fluent method individually even when RETURNS_SELF is available
- Not recognising that mocking a locally-owned builder is usually unnecessary