Using Mockito's `mockConstruction`, the object your code creates internally comes back as an unstubbed mock, so the very next call returns null and blows up. How do you give each constructed instance behaviour, and how do you get hold of the instances afterwards to assert on them?
answer
- second arg = MockInitializer (mock, context)
- context.getCount() / arguments() / constructorType()
- stub before first use — chained `new` leaves no gap
- constructed() = ordered snapshot
- mockConstructionWithAnswer for uniform behaviour
basics
~20 sPass a MockInitializer as the second argument: mockConstruction(Foo.class, (mock, context) -> when(mock.get()).thenReturn("x")). It runs right after each construction, so the mock is stubbed before the code uses it. Afterwards read scope.constructed() — the ordered list of every instance created.
solid answer
~40 sThe two-argument overload takes a `MockedConstruction.MockInitializer<Foo>`, a callback invoked immediately after each interception with the fresh mock and a `Context`. Stub inside that callback so the instance is ready before the code under test touches it — stubbing after the fact is too late if construction and use happen in the same statement. The `Context` exposes `getCount()` (1-based construction index), `arguments()` (the actual constructor arguments) and `constructorType()`, so different instances can get different behaviour, and you can assert the arguments the production code passed. ```java try (MockedConstruction<Parser> m = mockConstruction(Parser.class, (mock, ctx) -> when(mock.parse()) .thenReturn(ctx.getCount() == 1 ? first : second))) { service.run(); assertEquals(2, m.constructed().size()); verify(m.constructed().get(0)).parse(); } ``` `constructed()` is an ordered snapshot of every mock created in the scope, and is the handle you verify against.
code
java · 16 linesList<Object> ctorArgs = new ArrayList<>();
try (MockedConstruction<Connection> mocked = Mockito.mockConstruction(
Connection.class,
(mock, context) -> {
ctorArgs.add(context.arguments().get(0));
when(mock.isOpen()).thenReturn(true);
when(mock.id()).thenReturn("conn-" + context.getCount());
})) {
pool.warmUp(2);
assertEquals(2, mocked.constructed().size());
assertEquals("jdbc:h2:mem", ctorArgs.get(0));
verify(mocked.constructed().get(1)).isOpen();
}go deeper
Recall the two-argument form and that constructed() gives you the created mocks in order.
Explain why stubbing must happen in the initializer, and use getCount() and arguments() correctly.
Discuss failure modes — assertions thrown from inside new, scope-wide accumulation of the list, uniform vs per-instance behaviour — and keep the initializer small.
Point out that a branching initializer encodes a construction protocol the design should express explicitly through a factory seam.
## The gap the initializer fills A plain `mockConstruction(Foo.class)` gives you a mock with default answers: `null` for objects, `0` for numbers, `false` for booleans, empty for collections. Production code that does `return new Foo(x).describe().trim()` therefore fails with a `NullPointerException` before your assertions run. You need the mock stubbed *between* construction and first use, and in a single chained expression there is no line of test code in between. The `MockInitializer` is that hook. ## MockInitializer ```java mockConstruction(Foo.class, (mock, context) -> { /* stub here */ }) ``` The lambda runs synchronously right after each interception, before control returns to the `new` expression's caller. Everything you can normally do to a mock — `when(...).thenReturn(...)`, `doThrow`, setting a custom answer — works here. Because it fires per construction, ten `new Foo()` calls run the initializer ten times. ## The Context object The second parameter, `MockedConstruction.Context`, describes *this particular* construction: - `getCount()` — 1-based ordinal of the construction within the scope. The idiom for giving the first and second instance different behaviour. - `arguments()` — `List<?>` of the actual arguments passed to the constructor. This is how you assert what the production code fed the collaborator, since there is no mock invocation to verify for a constructor call. - `constructorType()` — the reflective `Constructor<?>` chosen, useful when a class has several overloads and the behaviour should differ per overload. Be careful about assertions inside the initializer: it executes on the production call stack, so a failed assertion surfaces as an exception thrown from `new`, which the code under test may catch and turn into something unrecognisable. Capturing the arguments and asserting after the scope is often more debuggable. ## constructed() `MockedConstruction.constructed()` returns the ordered list of mocks produced so far in the scope, oldest first. It is the only way to reach an object the production code never handed back. Typical uses: - size assertions — "exactly one client was created, not one per loop iteration"; - `verify(constructed().get(0)).close()` — checking the created object was used and released; - `verifyNoMoreInteractions` across the list. The list is a snapshot view; read it inside the scope, and remember it accumulates across the whole scope, so a per-test scope keeps the indices meaningful. After `close()` the mocks still exist as objects and can be verified, but no new constructions are recorded. ## mockConstructionWithAnswer as the terse alternative When every constructed instance should behave the same and you only care about return values, `mockConstructionWithAnswer(Foo.class, answer, moreAnswers...)` is shorter: the answers apply to every method call on the constructed instances, with successive answers consumed by successive constructions. It cannot stub specific methods differently, so `MockInitializer` remains the expressive option. ## Practical shape Keep the initializer tiny — stub the one or two methods the path needs, nothing more. If the lambda grows a switch on `getCount()` with several branches, the test is describing a construction protocol that would read far better as an injected factory returning prepared mocks. That is a design signal, not a Mockito problem.
- How do you assert which arguments the production code passed to the intercepted constructor?Read `context.arguments()` inside the MockInitializer; it is the list of actual constructor arguments for that construction. There is no mock invocation for a constructor, so checking construction arguments has to happen through the context. Copying them into a list and asserting after the scope keeps failures readable.
- When would you choose mockConstructionWithAnswer over a MockInitializer?When every constructed instance should answer uniformly and you do not need method-specific stubbing — for example making all calls return a canned value or throw. It is shorter but blunter: you cannot stub one method differently from another, and successive answers are consumed per construction rather than per method call.
saying these in an interview costs you the question
- Stubbing the mock after the scope, then wondering why the code under test already NPE'd.
- Assuming the initializer runs once per scope rather than once per construction.
- Thinking constructor arguments can be checked with verify() on the mock.
- Treating constructed() as mutable or expecting it to be cleared between constructions.
- Putting heavy assertions inside the initializer and confusing the resulting exception with production behaviour.