What do the Mockito @Mock and @InjectMocks annotations do, and how do they work together in a unit test?
answer
- @Mock = fake collaborator; @InjectMocks = real SUT with mocks pushed in
- Injection order: constructor → setter → field
- Match by type, then by name
- Activate via MockitoExtension or openMocks(this)
- Unmatched dependency stays null silently
basics
~10 s@Mock creates a fake stand-in for a dependency. @InjectMocks creates the real object you are testing and pushes those mocks into it, so you can test it in isolation without its real collaborators.
solid answer
~40 s@Mock declares a mock: a fake implementation of a type whose methods do nothing and return defaults until you stub them. @InjectMocks tells Mockito to instantiate the real class under test and inject the available @Mock fields into it. The two are used together so the object under test runs against controllable fakes instead of real dependencies. They are activated by something that processes the annotations: the MockitoExtension on JUnit 5 (@ExtendWith(MockitoExtension.class)), or a manual MockitoAnnotations.openMocks(this) call in setup. Mockito tries to inject mocks first by constructor, then by property setters, then by direct field assignment, matching by type and then by name. A typical test mocks a repository, injects it into a service, stubs the repository with when(...).thenReturn(...), calls the service, and asserts the result.
go deeper
Can state that @Mock makes a fake dependency and @InjectMocks builds the real object under test with those fakes inside, and knows you need MockitoExtension to switch them on.
Explains the constructor→setter→field injection order, type-then-name matching, and that an unmatched dependency stays null rather than erroring.
Discusses strict-stubbing from MockitoExtension, openMocks vs deprecated initMocks, and the trade-off of @InjectMocks reflection magic vs explicit constructor wiring.
Frames @InjectMocks as a testability smell when overused, advocates constructor injection in production code so tests need no reflection, and sets team conventions for mocking boundaries.
## The problem these solve A **unit test** checks one class (the *system under test*, or SUT) in isolation. But classes rarely stand alone — a `UserService` calls a `UserRepository`, a `PasswordEncoder`, etc. These are its **collaborators** (dependencies). In a unit test you do not want to hit a real database or send real emails. You replace each collaborator with a **mock**: a fake object that implements the same type but whose behaviour you control. **Mockito** is the dominant Java mocking library. It lets you create mocks and tell them how to behave ("stubbing") and verify how they were called. ## @Mock `@Mock` is a field annotation that asks Mockito to create a mock of that field's type: ```java @Mock UserRepository repository; ``` This is equivalent to `repository = Mockito.mock(UserRepository.class)`. A fresh mock does nothing useful yet: every method returns a **default value** — `null` for objects, `0` for numbers, `false` for booleans, an empty collection for collection types. You then **stub** the methods you care about with `when(repository.findById(1L)).thenReturn(user)`. ## @InjectMocks `@InjectMocks` goes on the field holding the **real** object you want to test: ```java @InjectMocks UserService service; ``` Mockito will (a) instantiate `UserService` and (b) inject the other `@Mock`/`@Spy` fields in the same test class into it. So the real `UserService` runs, but its dependencies are your controllable mocks. Note: `@InjectMocks` creates a **real** instance, not a mock — only its dependencies are mocked. ## How injection is resolved (the order) Mockito tries three strategies, in this order: 1. **Constructor injection** — if the class has a constructor, Mockito picks the constructor with the most arguments it can satisfy and passes mocks in. (This is the preferred, modern style and works with `final` fields.) 2. **Property (setter) injection** — for any remaining unset dependencies, it calls matching setters. 3. **Field injection** — it writes directly into fields (even private ones, via reflection). Within each strategy, mocks are matched **by type**; if several mocks share a type, Mockito disambiguates **by field name**. Unmatched dependencies are simply left null — Mockito does **not** fail the test for them, which is a common source of surprise `NullPointerException`s. ## Turning the annotations on Annotations are inert until something processes them. Three options: - **JUnit 5:** annotate the test class with `@ExtendWith(MockitoExtension.class)`. This is the recommended modern approach; it also enforces *strict stubbing* (it fails the test if you stub something that is never used). - **Manual:** call `MockitoAnnotations.openMocks(this)` in an `@BeforeEach` method (it returns an `AutoCloseable` you can close in `@AfterEach`). The older `initMocks(this)` is deprecated in favour of `openMocks`. - **JUnit 4:** `@RunWith(MockitoJUnitRunner.class)` or the `MockitoRule`. Without one of these, the fields stay `null`. ## A complete example ```java @ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock UserRepository repository; @InjectMocks UserService service; @Test void returnsUserName() { when(repository.findById(1L)).thenReturn(new User(1L, "Ada")); assertEquals("Ada", service.nameOf(1L)); verify(repository).findById(1L); } } ``` ## Key caveats - `@InjectMocks` silently leaves a dependency null if no matching mock exists — you then get an NPE deep in the SUT, not a clear error. - Mixing constructor and field injection on the same class can produce a *partially* wired object if a constructor exists but cannot be fully satisfied. - Many teams now prefer **plain constructor calls** (`new UserService(repository)`) over `@InjectMocks` because it is explicit and fails loudly when a dependency is missing.
- If a class has both a constructor taking the dependency and a field, which injection strategy wins?Constructor injection is attempted first. If Mockito can satisfy the constructor, it uses it and won't also do field injection for those dependencies.
- Why might you prefer plain `new` over @InjectMocks?Constructor wiring is explicit, compiler-checked, and fails loudly if a dependency is missing, whereas @InjectMocks injects by reflection and silently leaves unmatched dependencies null.
saying these in an interview costs you the question
- Saying @InjectMocks creates a mock of the class under test (it creates a REAL instance)
- Thinking the annotations work without MockitoExtension / openMocks
- Believing Mockito errors when a dependency can't be injected (it leaves it null)
- Confusing @Mock with @Spy (a spy wraps a real object and calls real methods by default)