What are the ways to create a Mockito mock in a Java test, and what practical difference is there between calling Mockito.mock(Foo.class) and declaring a field annotated with Mockito's @Mock?
answer
- mock(Class) vs @Mock field — same object
- annotation needs an initializer, else null
- field name = mock name in failure output
- only @Mock feeds injection
- withSettings() for anything the annotation cannot express
basics
~20 sTwo forms produce the same kind of object: the programmatic Mockito.mock(Foo.class) (optionally with settings) and the declarative @Mock Foo foo; field. The annotation is shorter, names the mock after the field for better failure messages, and needs an initializer to run; mock() works anywhere, including inside a method or with generics.
solid answer
~50 s`Mockito.mock(Foo.class)` creates a mock inline and returns it; overloads take a name, a default `Answer`, or a full `MockSettings` from `withSettings()`. Mockito 5 also adds `mock(Foo.class)` type-inference-friendly overloads so `List<String> l = mock();` compiles without an unchecked cast. `@Mock Foo foo;` is the declarative equivalent. It is processed by an initializer — the Mockito JUnit 5 extension, `MockitoAnnotations.openMocks(this)`, or the JUnit 4 runner/rule — and until that runs the field is null. The annotation carries the same settings as attributes: `@Mock(name=…, answer=…, lenient=true, extraInterfaces=…)`. Differences that matter in practice: annotated mocks get the field name, so failure and `toString()` output reads `orderRepository` instead of `Mock for OrderRepository`; annotated fields are re-created for each test method; and only annotated fields participate in constructor/field injection into a class under test. Use `mock()` for local, one-off, or conditionally-created mocks.
code
java · 13 linesclass CheckoutServiceTest {
@Mock OrderRepository orderRepository; // named "orderRepository"
@Mock(answer = Answers.RETURNS_SMART_NULLS) PaymentGateway gateway;
@Test
void appliesCoupon() {
// local, one-off mock: no annotation needed
Clock fixedClock = Mockito.mock(Clock.class, "fixedClock");
List<String> codes = Mockito.mock(); // Mockito 5 generic inference
...
}
}go deeper
Know both forms exist, that they create the same thing, and that the annotated field needs an initializer while mock() does not.
Add naming in failure messages, per-test lifecycle, the generics story, and that only annotated mocks feed injection.
Discuss when you deliberately prefer explicit mock() plus a real constructor call over annotations, and the leakage bug when a mock is hoisted to a static or @BeforeAll field.
Frame it as test-readability policy: declared collaborators at the top of the class document the unit's dependencies, while constructing the subject explicitly keeps compile-time feedback when its dependencies change.
## The two creation styles Mockito offers a programmatic API and a declarative one, and they produce equivalent objects. **Programmatic:** ```java OrderRepository repo = Mockito.mock(OrderRepository.class); OrderRepository named = Mockito.mock(OrderRepository.class, "repo"); OrderRepository smart = Mockito.mock(OrderRepository.class, Answers.RETURNS_SMART_NULLS); OrderRepository tuned = Mockito.mock(OrderRepository.class, withSettings().name("repo").defaultAnswer(RETURNS_SMART_NULLS)); ``` **Declarative:** ```java @Mock OrderRepository orderRepository; @Mock(name = "repo", answer = Answers.RETURNS_SMART_NULLS) OrderRepository tuned; ``` The annotation attributes mirror the settings object: `name`, `answer`, `extraInterfaces`, `lenient`, `stubOnly`, `serializable` (availability varies slightly by version). Anything expressible on `@Mock` is expressible via `withSettings()`, but the reverse is not true — a custom `Answer` instance, `verboseLogging()`, `mockMaker(...)` or `withoutAnnotations()` need the programmatic form. ## What actually differs **1. Something has to process the annotation.** A bare `@Mock` field is just metadata; the field stays `null` until an initializer walks the test instance's fields. That initializer is a separate concern (a JUnit 5 extension, an explicit `MockitoAnnotations.openMocks(this)` call, or the JUnit 4 runner/rule) and is the single most common source of "my mock is null" confusion. `Mockito.mock()` has no such prerequisite: it works in any framework, in a helper method, in a static factory, or inside a loop. **2. Naming and error messages.** An annotated mock takes the field name, so verification failures and `toString()` read `orderRepository.findById(1L)` instead of the generic `orderRepository` being printed as `Mock for OrderRepository, hashCode: 1234567`. With `mock()` you get the generic name unless you pass one explicitly — worth doing when a test holds several mocks of the same type, because otherwise two mocks of `Clock` are indistinguishable in the failure output. **3. Lifecycle.** Annotated fields are re-initialized per test method by the standard initializers, so each test gets fresh mocks with empty stubbing and empty invocation history — no leakage between tests. Mocks created with `mock()` live exactly as long as the reference you hold: a local variable is per-test by construction, but a mock assigned to a `static` field or created once in a `@BeforeAll` is shared, and stale stubbing or recorded invocations then leak across tests. That is a real bug source, not a style preference. **4. Injection.** Only annotated mocks are candidates for Mockito's injection into a `@InjectMocks` target. If you create collaborators with `mock()`, you wire the class under test yourself — usually by calling its constructor, which many teams prefer precisely because it is explicit and fails to compile when the constructor changes. **5. Generics.** `mock(List.class)` gives you a raw `List`, so assigning to `List<String>` produces an unchecked warning; the classic workarounds were a cast or `@SuppressWarnings`. `@Mock List<String> names;` has always been clean, since the field carries the type. Mockito 5 added generic-inference overloads so `List<String> names = mock();` also compiles warning-free. ## Which to choose A reasonable default: use `@Mock` for the collaborators the whole test class shares, because it reads as a declaration of the test's dependencies and gives good names for free; use `mock()` for mocks that are local to a single test, created conditionally, built in a helper/builder, or that need settings the annotation cannot express. Mixing both in one class is fine and common. One subtlety worth knowing: mocks are also created implicitly in other places — `@Captor`, deep stubs, and `RETURNS_MOCKS` all mint mocks you never called `mock()` for. And in a Spring Boot test the analogous annotation is Spring's own bean-replacing annotation, which is a different mechanism (it registers a mock in the application context) even though it too ends up calling Mockito's `mock()` underneath. ## Interview framing Say: same object, two ergonomics. Then give the concrete differences — annotation needs an initializer and is per-test, gives the mock the field name, participates in injection, and handles generics cleanly; `mock()` is framework-independent, works for locals and helpers, and unlocks the full settings API. Ending with "and I name mocks explicitly when a test holds two of the same type, because the failure message is otherwise unreadable" shows you have actually debugged such a test.
- You need two mocks of the same type in one test and the failure message is ambiguous. What do you do?Give each mock an explicit name — `mock(Clock.class, "startClock")` and `mock(Clock.class, "endClock")`, or use `withSettings().name(...)`. With `@Mock` you get the field name automatically, which is one reason annotated mocks read better in failure output. The name appears in `toString()` and in verification failure messages, which turns an unreadable diff into an obvious one.
- How do you mock a generic type such as List<String> without an unchecked warning?On Mockito 5, `List<String> names = Mockito.mock();` — the new overloads infer the type from the assignment target. On earlier versions, declare it as a `@Mock List<String> names;` field, or cast the raw `mock(List.class)` and suppress the warning. In practice, mocking collections is itself a smell; a real `ArrayList` is usually the better test double.
saying these in an interview costs you the question
- Believing @Mock and mock() create different kinds of objects with different behaviour
- Assuming a @Mock field is populated just by declaring it
- Creating mocks once in a static field or @BeforeAll and expecting per-test isolation
- Thinking every setting available in withSettings() is also available as a @Mock attribute
- Claiming mock() cannot be used in a JUnit 5 test class