When Mockito creates a mock of a concrete Java class, is that class's constructor executed and are its fields initialized? Explain how the mock object comes into existence.
answer
- Byte Buddy makes the type, Objenesis makes the instance
- no constructor, no field initializers — all defaults
- subclass maker: final class/method not mockable
- inline maker default since Mockito 5
- equals/hashCode never intercepted; static init still runs
basics
~20 sNo constructor runs and no field initializer runs. Mockito generates a subclass (or, with the inline mock maker, instruments the class) and allocates an instance without calling any constructor, using Objenesis. All fields stay at their JVM defaults, and every method is intercepted, so no real code executes.
solid answer
~50 sMock creation has two steps. First, a **type** is produced: the classic subclass mock maker uses Byte Buddy to generate a subclass overriding every non-final, non-private method; the inline mock maker (default since Mockito 5) instead retransforms the original class's bytecode with a Java agent, which is what allows final classes and final methods to be mocked. Second, an **instance** is produced without running any constructor — Mockito uses Objenesis, which allocates the object the way deserialization does. Consequences: field initializers and constructor side effects never happen, so all fields are null/0/false; that is fine because every method is intercepted anyway, but code that reads a field directly (or a final method the subclass maker cannot override) sees the uninitialized value. With the subclass maker, final classes, final methods, private methods, static methods and equals/hashCode are not intercepted. The inline maker covers final classes and methods; equals/hashCode and constructors are still off-limits.
code
java · 14 linesclass Counter {
private int value = 42; // never runs for a mock
Counter() { throw new IllegalStateException("never called"); }
int value() { return value; }
}
@Test
void mockIsBuiltWithoutAConstructor() {
Counter c = Mockito.mock(Counter.class); // no exception thrown
assertEquals(0, c.value()); // intercepted -> int default 0
Counter real = Mockito.mock(Counter.class, Answers.CALLS_REAL_METHODS);
assertEquals(0, real.value()); // real body, uninitialised field
}go deeper
Know the headline: no constructor runs, fields are defaults, no real code executes unless you ask for it.
Name Byte Buddy for the type and Objenesis for the instance, and list what the subclass maker cannot intercept.
Explain the subclass-vs-inline mock maker tradeoff, the surviving static-initializer problem, and why mocking data classes is a smell given uninitialized state.
Argue about mockability as a design signal: needing the inline maker to mock final third-party types usually means the seam belongs at your own boundary interface instead.
## Step 1 — generating the mock type Mockito never uses reflection proxies alone; it generates bytecode through Byte Buddy. Which strategy it uses depends on the configured **mock maker**: - **Subclass mock maker** (`mock-maker-subclass`; the default before Mockito 5 and still available). Byte Buddy generates a subclass of your class — or an implementation of your interface — that overrides every method it legally can and routes the call into Mockito's interception handler. Because it is plain Java subclassing, everything Java forbids overriding is invisible to Mockito: `final` classes cannot be mocked at all, and `final`, `private` and `static` methods keep running their real implementation. - **Inline mock maker** (`mock-maker-inline`; the default since Mockito 5, and opt-in via the `mockito-inline` artifact on Mockito 3/4). Instead of subclassing, it attaches a Java agent and retransforms the loaded class's bytecode so that method bodies first check whether the receiver is a registered mock. That removes the final-class and final-method restrictions and is the mechanism the static/construction mocking features build on. Either way, the generated type is cached per class + settings, so creating a thousand mocks of the same interface does not regenerate a thousand classes. ## Step 2 — instantiating without a constructor This is the part candidates usually miss. Mockito does **not** call any constructor of the mocked class. It uses **Objenesis**, a small library that allocates an instance through JVM-specific back doors (the same machinery deserialization uses). Therefore: - No constructor body runs — no validation, no registration with a listener, no logging, no thread started. - No field initializers run, and no instance initializer blocks. - Every field, including `final` ones, holds the JVM default: `null`, `0`, `false`. - Superclass constructors do not run either. That is exactly what you want for a test double: you must be able to mock a class whose constructor demands a live database connection. But it explains several confusing behaviours: 1. **Direct field access sees nulls.** If code under test reads `mock.someField` rather than calling a getter, it gets null — there is nothing to intercept, because field reads are not method calls. 2. **A real method you deliberately invoke may NPE.** With `CALLS_REAL_METHODS`, or when you mock a class whose `final` method the subclass maker could not override, the real body runs against an object whose fields were never initialized. 3. **`toString()`, `equals()`, `hashCode()`.** `equals()` and `hashCode()` are never intercepted or stubbable — Mockito needs identity semantics for its own registry — so a mock uses reference equality. `toString()` is intercepted and returns a readable mock name. ## What can and cannot be mocked | Feature | Subclass maker | Inline maker | |---|---|---| | Interfaces, non-final classes | yes | yes | | `final` classes | no | yes | | `final` methods | no (real body runs) | yes | | `private` methods | no | no | | `static` methods | no | via `mockStatic` | | Constructors | never run | never run | | `equals` / `hashCode` | never stubbable | never stubbable | | Anonymous / local classes, primitives | no | no | A class with no no-arg constructor is not a problem in either case, precisely because no constructor is invoked. What *is* a problem is a `final` class on the old subclass maker: Mockito fails fast with a message telling you the type cannot be mocked and pointing at the mock-maker options. ## Practical implications for test design - Because construction is bypassed, mocking a class is cheap and independent of how hostile its constructor is. This is why people reach for mocks around legacy code that cannot be instantiated in a test. - Because fields stay null, do not mock a value/data class and then expect its state to behave: use a real instance or a builder. Mocking data holders is a classic smell — you end up stubbing getters that a real object would just answer. - Because the real class's static initializer *does* run when the class is loaded (loading is not bypassed — only construction is), a class whose `static` block requires configuration can still blow up at mock time. That surprises people who think mocking isolates them from the class entirely. - The inline maker's instrumentation makes it slightly slower and means mocks are held in a registry that must be released; that is why sessions/close matter for large suites. ## Interview framing The crisp answer is: *type* via Byte Buddy (subclass, or bytecode instrumentation with the inline maker), *instance* via Objenesis with no constructor call, so all fields are defaults and no real code runs. Then name one consequence you have actually hit — direct field reads returning null, or a final method still executing on the old mock maker.
- You get an error saying a final class cannot be mocked. What are your options?Either switch to the inline mock maker — the default on Mockito 5, or the `mockito-inline` artifact / a `mockito-extensions/org.mockito.plugins.MockMaker` resource containing `mock-maker-inline` on older versions — or avoid mocking it: extract an interface you own, or use a real instance. Preferring a real instance is often the better answer for value types and small final classes, since mocking them adds no isolation.
- Why does a mocked class's static initializer still run even though its constructor does not?Mockito bypasses construction, not class loading. To generate a subclass or instrument the type, the JVM must load and initialize the class, which runs its `static` block. So a class whose static initializer needs configuration or a network resource can still fail at mock-creation time; the fix is to make the static initialization lazy or to isolate it behind an interface.
It is like a crash-test dummy stamped from the same mould as the car's driver: the shape is right, but nothing inside was ever assembled, and it only reacts the way you scripted.
saying these in an interview costs you the question
- Saying Mockito calls the real no-arg constructor to build the mock
- Assuming a class must have a default constructor to be mockable
- Claiming Mockito uses JDK dynamic proxies, so only interfaces can be mocked
- Thinking final methods are mocked by the subclass mock maker (they silently run for real)
- Believing equals() and hashCode() can be stubbed like any other method