How do you select which mock maker Mockito uses, and what happened to the mockito-inline artifact people used to add to their test dependencies?
answer
- mockito-extensions/org.mockito.plugins.MockMaker resource
- content: mock-maker-inline / mock-maker-subclass
- Mockito 5 default = inline in mockito-core
- mockito-inline retired; mockito-subclass for the old behaviour
- @Mock(mockMaker = MockMakers.SUBCLASS) since 4.8
basics
~20 sSince Mockito 5 the inline maker is the default in mockito-core, so nothing is needed. Otherwise put a file mockito-extensions/org.mockito.plugins.MockMaker on the test classpath containing mock-maker-inline. The mockito-inline artifact existed only to flip that default and is retired; mockito-subclass now provides the old behaviour.
solid answer
~40 sThree levels of control: 1. **Default.** Mockito 5.0+ ships the inline maker as the default of `mockito-core`. On Mockito 2–4 the default was the subclass maker. 2. **Classpath-wide override.** Create `src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker` whose single line is `mock-maker-inline` or `mock-maker-subclass`. Mockito's plugin loader reads that resource at startup. (A fully-qualified `MockMaker` implementation class name works too, for custom makers.) 3. **Per mock.** Since Mockito 4.8: `@Mock(mockMaker = MockMakers.SUBCLASS)` or `mock(Foo.class, withSettings().mockMaker(MockMakers.INLINE))`. The old `mockito-inline` artifact was nothing but `mockito-core` plus that resource file preselecting the inline maker. Once Mockito 5 made inline the default it became redundant and was discontinued after 5.2. If you still need the subclass behaviour — Android, or a JVM where the agent cannot attach — depend on `mockito-subclass` instead.
code
java · 15 lines@ExtendWith(MockitoExtension.class)
class MixedMakersTest {
@Mock(mockMaker = MockMakers.SUBCLASS)
LegacyService legacy;
@Test
void inlineForOneMock() {
FinalConfig config = mock(FinalConfig.class,
withSettings().mockMaker(MockMakers.INLINE));
when(config.timeoutSeconds()).thenReturn(5);
assertEquals(5, config.timeoutSeconds());
}
}go deeper
Know that Mockito 5 needs no extra setup for final classes, and that mockito-inline was the old opt-in.
Describe the extensions resource file, its two token values, and the artifact history including mockito-subclass.
Handle multi-module and BOM-managed builds, competing extension resources, and per-mock MockMakers selection.
Set a project-wide convention for mock-maker selection and treat a Mockito major bump as a behavioural change requiring a note in the migration plan.
## The plugin mechanism `MockMaker` is one of Mockito's service-provider extension points. At startup Mockito's plugin loader looks for a resource named `mockito-extensions/org.mockito.plugins.MockMaker` anywhere on the classpath. The file's content is a single token naming the implementation: - `mock-maker-inline` — the instrumentation-based maker; - `mock-maker-subclass` — the classic ByteBuddy subclassing maker; - or the fully qualified class name of your own `MockMaker`. The same directory hosts sibling extension points (`org.mockito.plugins.MockitoLogger`, `...InstantiatorProvider2`, `...StackTraceCleanerProvider`). In a Gradle or Maven project the file goes to `src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker` so it lands on the test runtime classpath. A sharp edge: only one such resource should be visible. If two dependencies each contribute one, which wins is classpath-order dependent and effectively arbitrary — a real source of "works on my machine" behaviour. ## The artifact history - **Mockito 2–4**: `mockito-core` defaults to the subclass maker. To get the inline maker you either wrote the resource file yourself or depended on **`mockito-inline`**, an artifact that was simply `mockito-core` with that resource baked in. That is the only thing it ever did. - **Mockito 5.0 (2023)**: the default in `mockito-core` flipped to the inline maker, and the minimum Java version rose to 11. `mockito-inline` became a no-op wrapper and was discontinued (its last release is in the 5.x line); build files that still reference it should just drop the dependency. - **`mockito-subclass`**: introduced alongside Mockito 5 as the mirror image — `mockito-core` plus a resource preselecting `mock-maker-subclass` — for environments where instrumentation is not available or not wanted. Interviewers ask about this because plenty of build files still carry `mockito-inline` on Mockito 5, which is dead weight, and because knowing *why* it existed demonstrates understanding of the plugin mechanism rather than dependency cargo-culting. ## Per-mock selection Mockito 4.8 added a way to choose the maker for a single mock, which is useful when the classpath-wide choice does not suit one particular type: ```java @Mock(mockMaker = MockMakers.SUBCLASS) LegacyService legacy; HeavyType heavy = mock(HeavyType.class, withSettings().mockMaker(MockMakers.INLINE)); ``` `MockMakers` holds the constants `INLINE` and `SUBCLASS` (the same tokens as the resource file). Typical reasons to reach for it: a type that the inline maker cannot instrument, or a hot path in a large suite where subclass mocks are cheaper for a repeatedly mocked simple interface. ## Verifying what is actually active When in doubt, the fastest empirical check is behavioural: try mocking a final class. If it fails with "Cannot mock/spy because: final class", the subclass maker is active. `Mockito.framework().getPlugins().getInlineMockMaker()` and the mock-maker information Mockito prints in some failure messages also help. In a multi-module build, check every module's test classpath — the resource file only affects modules that can see it, so one module can behave differently from another. ## Spring Boot and managed dependencies If the Mockito version comes from a BOM (Spring Boot's dependency management, for instance), the mock-maker default follows that managed version. Overriding `mockito.version` to move from 4.x to 5.x therefore changes mocking behaviour project-wide — usually for the better, but it is a real behavioural change to note in a version bump, especially for suites that relied on final methods running for real on spies.
- A project on Mockito 5 still declares mockito-inline as a test dependency. What should you do?Remove it. On Mockito 5 mockito-core already defaults to the inline maker, so the artifact adds nothing and is no longer released alongside new versions; keeping it risks pinning an older Mockito on the classpath. If the project genuinely needs the subclass maker, swap to mockito-subclass rather than keeping the retired artifact.
- Two libraries on your test classpath each ship a MockMaker extension resource. What happens?Mockito's plugin loader picks one, and which one depends on classpath ordering, so the effective mock maker becomes non-deterministic across environments. The remedy is to make the choice explicit in your own module — your own resource file or per-mock MockMakers settings — and to exclude the transitive artifact that carries the competing resource.
- When would you deliberately choose MockMakers.SUBCLASS for a single mock?When the type cannot be instrumented safely or the inline path fails for it, or when profiling shows repeated instrumentation cost for a simple, heavily mocked interface. It is also a quick isolation step while diagnosing whether a strange test failure comes from instrumentation. Otherwise leave the classpath default in place.
saying these in an interview costs you the question
- Thinking mockito-inline is still required on Mockito 5
- Believing the mock maker is chosen by an API call at runtime only (missing the resource file)
- Putting the extensions resource in main resources instead of test resources
- Not knowing mockito-subclass exists for environments without instrumentation
- Assuming the resource file affects modules that cannot see it on their classpath