skip to content

How does the @Mock annotation relate to Mockito.mock(Class), and what is required to make @Mock fields actually become mocks?

level: middleimportance: must knowfreq 70%

answer

  1. @Mock == mock(SomeClass.class), just declarative
  2. annotation does nothing until processed
  3. @ExtendWith(MockitoExtension.class) in JUnit 5
  4. or MockitoAnnotations.openMocks(this)
  5. forget it -> fields null -> NPE

basics

~10 s

@Mock is shorthand for Mockito.mock(SomeClass.class) on a field. But the annotation does nothing by itself — you must initialize it, either with @ExtendWith(MockitoExtension.class) (JUnit 5) or MockitoAnnotations.openMocks(this) in a setup method.

solid answer

~50 s

Functionally @Mock and Mockito.mock(Class) produce the same mock; @Mock is just declarative sugar that removes boilerplate when a test has several collaborators. The catch is that a bare @Mock field stays null until something processes the annotations. In JUnit 5 the idiomatic way is @ExtendWith(MockitoExtension.class) on the test class, which creates the mocks before each test (and, by default, applies strict stubbing that flags unused stubs and argument mismatches). The framework-agnostic way is to call MockitoAnnotations.openMocks(this) in an @BeforeEach (it returns an AutoCloseable you can close in @AfterEach). The old MockitoJUnitRunner is the JUnit 4 equivalent. If you forget all of these, your @Mock fields are null and you get NullPointerExceptions, which is a classic Mockito gotcha. @Mock can also auto-inject mocks into an @InjectMocks SUT. mock(Class) needs none of this — it's self-contained and works anywhere, including inside a test method body or in non-test code.

go deeper

for a junior

Knows @Mock is a shorter way to write mock(Class) and that you need an extension or openMocks to use it.

for a middle

Can wire a JUnit 5 test with MockitoExtension and @InjectMocks, and explains the null-field NPE that comes from skipping initialization.

for a senior

Discusses strict-stubs hygiene, openMocks AutoCloseable cleanup with the inline mock maker, and when to prefer programmatic mock(Class).

for a principal

Sets team conventions (strict stubbing on, extension over runner, cleanup) and reasons about how annotation processing and the mock maker affect test isolation and resource leaks at scale.

## Two ways to make a mock There are two surfaces for the same underlying operation: ```java // 1. Programmatic OrderRepository repo = Mockito.mock(OrderRepository.class); // 2. Declarative @Mock OrderRepository repo; ``` Both ultimately call the same Mockito machinery and yield an identical mock object. `@Mock` exists purely to reduce boilerplate: when a test class has four or five collaborators, declaring them as annotated fields is cleaner than five `mock(...)` assignments, and it pairs with `@InjectMocks` (which constructs the SUT and injects the matching mocks). ## The crucial difference: annotations must be *processed* A Java annotation is just metadata; it does nothing on its own. `@Mock OrderRepository repo;` declares a field whose value is **`null`** until some code reads the annotation and assigns a mock. That processing step is the source of the most common Mockito mistake — forgetting it leaves every `@Mock` field null, and the first call on it throws `NullPointerException`. There are three standard ways to trigger processing: ### a) JUnit 5 extension (preferred) ```java @ExtendWith(MockitoExtension.class) class OrderServiceTest { @Mock OrderRepository repo; @InjectMocks OrderService service; } ``` `MockitoExtension` hooks into JUnit 5's lifecycle, creating fresh mocks before each test method and validating usage after. By default it runs in **STRICT_STUBS** mode: it fails the test if you stub a method that is never called (an unnecessary stub) or call a stubbed method with arguments that don't match, catching dead/incorrect stubs early. ### b) `openMocks` (framework-agnostic) ```java class OrderServiceTest { @Mock OrderRepository repo; AutoCloseable closeable; @BeforeEach void setup() { closeable = MockitoAnnotations.openMocks(this); } @AfterEach void tearDown() throws Exception { closeable.close(); } } ``` `MockitoAnnotations.openMocks(this)` scans `this` object for Mockito annotations and populates the fields. It returns an `AutoCloseable`; closing it (in `@AfterEach`) releases mock state — important with the inline mock maker to avoid memory leaks across many tests. (`initMocks` is the deprecated predecessor.) ### c) JUnit 4 runner ```java @RunWith(MockitoJUnitRunner.class) // JUnit 4 only ``` ## Why `mock(Class)` needs none of this `Mockito.mock(...)` is a plain method call that immediately returns a mock. There is no annotation to process, so it works in any context: inside a test method, in a helper, in a `@BeforeEach`, even outside tests. The trade-off is verbosity and that it does not participate in `@InjectMocks` auto-wiring. ## Choosing between them - Few collaborators / dynamic creation inside a method → `mock(Class)`. - Several collaborators + a SUT to wire → `@Mock` + `@InjectMocks` + `MockitoExtension`, for readability and strict-stub hygiene. They can be mixed in one test freely, since they create the same kind of object.

  • What happens if you use @Mock but forget @ExtendWith(MockitoExtension.class) and openMocks?
    The annotated fields are never initialized, so they stay null, and the first method call on them throws NullPointerException.
  • What does MockitoExtension's default strict-stubs mode catch?
    Unnecessary stubbings (stubbed methods never called) and potential argument mismatches, surfacing them as test failures so dead or wrong stubs don't silently linger.

saying these in an interview costs you the question

  • Believing @Mock fields are populated automatically with no extension or openMocks call
  • Confusing MockitoExtension (JUnit 5) with MockitoJUnitRunner (JUnit 4)
  • Saying @Mock and mock(Class) produce different kinds of object
  • Forgetting that MockitoExtension's strict stubs can fail tests on unused stubs

context