skip to content

In Mockito, what does the @InjectMocks annotation do to the field it is placed on, and where does it get the values it injects?

level: juniorimportance: must knowfreq 70%

answer

  1. Field under test = real object, not a mock
  2. Mocks pulled from @Mock/@Spy fields of the test class
  3. Constructor → setter → field
  4. Needs MockitoExtension / openMocks or it's null
  5. Rebuilt fresh per test method

basics

~20 s

@InjectMocks makes Mockito create a real instance of that field's type and push the test class's @Mock and @Spy fields into it as dependencies. The field under test is a real object, not a mock — only its collaborators are mocks.

solid answer

~50 s

`@InjectMocks` marks the **object under test**. Mockito instantiates that type for real and then supplies its dependencies from the mocks declared in the same test class (fields annotated `@Mock` or `@Spy`), matching by type and, where several candidates share a type, by field name. It injects through one of three routes — constructor, property setter, or direct field write — trying them in that order and using the first that works. Two things people get wrong. First, the `@InjectMocks` field is **not** a mock: its methods run for real, which is the whole point. Second, injection only happens when the annotations are processed (via the JUnit 5 `MockitoExtension`, `MockitoAnnotations.openMocks(this)`, or the JUnit 4 runner); without that the field stays null. The object is rebuilt fresh before each test method, so state does not leak between tests.

code

java · 17 lines
java
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock OrderRepository repository;
    @Mock Mailer mailer;

    @InjectMocks OrderService service;

    @Test
    void placesOrderAndNotifies() {
        when(repository.save(any(Order.class))).thenAnswer(inv -> inv.getArgument(0));

        service.placeOrder(new Order("book", 2));

        verify(mailer).sendConfirmation(anyString());
    }
}

go deeper

for a junior

Be able to state the split cleanly: collaborators are mocks, the @InjectMocks field is the real class under test, and something has to initialize the annotations.

for a middle

Add that injection is attempted constructor-first and that same-type mocks are disambiguated by field name; know that unmatched dependencies silently stay null.

for a senior

Frame it as a convenience over explicit construction and note where it hides refactoring breakage — a new constructor parameter compiles and silently arrives as null.

for a principal

Talk about it as a suite-wide convention: consistency, readability for newcomers, and whether the team wants wiring mistakes to fail at compile time instead of at NPE time.

## The problem it solves A typical unit test has one class you actually want to exercise and several collaborators you want to fake. Written by hand, the setup looks like this: create a mock repository, create a mock mailer, then `new OrderService(repository, mailer)`. `@InjectMocks` automates the third line. You declare the collaborators as `@Mock` fields, annotate the field holding the class under test with `@InjectMocks`, and Mockito builds the object and hands it the mocks. ## What the annotated field actually holds The `@InjectMocks` field holds a **real instance** of its declared type. Mockito does not proxy it, does not intercept its methods, and does not record calls on it. When your test calls `service.placeOrder(...)`, the genuine production code runs. That is deliberate: the class under test must be real, or the test asserts nothing about your code. Only the things it talks to are replaced. Because it is real, you cannot `verify(...)` calls on it or stub its methods — attempting to do so throws `NotAMockException`. If you truly need to stub one of its own methods you have to make it a spy instead, which is a different (and much more contentious) technique. ## Where the injected values come from Mockito scans the **test class instance**, including inherited fields from superclasses, for fields annotated `@Mock` or `@Spy`. Those become the pool of injection candidates. Anything else in the test class — a plain `new Clock()` field, a constant, a value you assigned in `@BeforeEach` — is invisible to the mechanism. This surprises people: if a dependency has no `@Mock` field of the right type, Mockito leaves it as `null` rather than complaining. Matching is by **type** first. When exactly one candidate matches a dependency's type, it is used. When several mocks share a type (two `DataSource` mocks, say), Mockito falls back to matching the **field name** of the mock against the name of the target field or setter, which is why naming your mocks after the fields they replace is more than cosmetic. ## How the value gets in Mockito tries, in order: pass the mocks as **constructor arguments**; call **setters** whose parameter type matches a mock; write directly to the **fields** by reflection. It uses the first strategy that succeeds — it does not combine them. The important consequence for a beginner is that you do not need setters or public fields: a class with a normal constructor is wired through that constructor, which is also the design most teams want. ## It does nothing on its own The annotations are inert metadata. Something must process them: - JUnit 5: `@ExtendWith(MockitoExtension.class)` on the test class. - Any framework, manually: `MockitoAnnotations.openMocks(this)` in a `@BeforeEach`, ideally closing the returned `AutoCloseable`. - JUnit 4: `@RunWith(MockitoJUnitRunner.class)` or `MockitoRule`. Without one of these, every annotated field is `null` and the first line of your test throws a `NullPointerException`. This is the single most common "my Mockito test doesn't work" cause. ## Lifecycle JUnit creates a new test-class instance per test method, and annotation processing runs per test method too. So both the mocks and the `@InjectMocks` object are recreated for every test — stubs, recorded interactions and any state mutated inside the object under test do not bleed into the next test. That isolation is free, and you should not fight it by making the fields `static`. ## A worked shape ```java @ExtendWith(MockitoExtension.class) class OrderServiceTest { @Mock OrderRepository repository; // fake collaborator @Mock Mailer mailer; // fake collaborator @InjectMocks OrderService service; // REAL object under test } ``` Inside a test, you stub `repository`, call `service.placeOrder(...)` for real, and `verify(mailer)` afterwards. The mental model is a triangle: stub the inputs, run the real thing, verify the outputs. ## When it is not worth it For a class with one or two dependencies, `new OrderService(repository, mailer)` in a `@BeforeEach` is just as short, fails loudly when the constructor changes, and is obvious to a reader. `@InjectMocks` earns its keep on wider constructors and in suites where that pattern is already established — but it is a convenience, not a requirement, and it hides wiring errors rather than reporting them.

  • Can you call verify() or when() on the field annotated @InjectMocks?
    No. That field holds a real instance, so Mockito has no interception hooks on it and throws NotAMockException. Only the @Mock and @Spy collaborators can be stubbed or verified. If you genuinely need to control one of the object-under-test's own methods, you have to combine @Spy with @InjectMocks, which turns it into a partial mock and is usually a signal the class should be split.
  • What happens if you forget @ExtendWith(MockitoExtension.class) on a JUnit 5 test class?
    Nothing processes the annotations, so every @Mock and @InjectMocks field stays null and the test fails with a NullPointerException on first use. The fix is either the extension, or MockitoAnnotations.openMocks(this) in a @BeforeEach with the returned AutoCloseable closed in @AfterEach.
  • How does Mockito choose between two @Mock fields of the same type?
    It filters candidates by type first; when more than one survives, it compares the mock field's name with the name of the target field or setter property. So naming the mock after the field it replaces is what makes the disambiguation work. If names do not line up, the safest fix is to construct the object explicitly rather than rely on the heuristic.

Think of it as a tiny dependency-injection container scoped to one test class: the @Mock fields are the bean registry, and @InjectMocks is the single bean it is asked to assemble.

saying these in an interview costs you the question

  • Saying the @InjectMocks field is itself a mock, or trying to stub/verify it
  • Assuming the annotation works without MockitoExtension, the runner, or openMocks
  • Thinking Mockito can inject arbitrary objects created in the test, not just @Mock/@Spy fields
  • Expecting a loud error when a dependency cannot be matched — Mockito stays silent and leaves null

context