Mocking
Unit Testing
Software Development
Java Annotations
Dependency Injection

Difference between @Mock and @InjectMocks

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Mockito, @Mock and @InjectMocks serve different roles in a unit test. @Mock creates a test double for a dependency, while @InjectMocks creates the object under test and tries to inject the available mocks into it.

@Mock Creates a Mocked Dependency

Use @Mock on collaborators whose behavior you want to control.

java
1import org.junit.jupiter.api.Test;
2import org.junit.jupiter.api.extension.ExtendWith;
3import org.mockito.Mock;
4import org.mockito.junit.jupiter.MockitoExtension;
5
6@ExtendWith(MockitoExtension.class)
7class PaymentServiceTest {
8
9    @Mock
10    PaymentGateway gateway;
11}

That field is not a real PaymentGateway. It is a Mockito-generated mock that returns default values until you stub it.

java
when(gateway.charge(anyInt())).thenReturn(true);

The whole point of @Mock is to isolate the unit under test from real external behavior.

@InjectMocks Creates the Subject Under Test

@InjectMocks is applied to the class you actually want to test.

java
1import org.mockito.InjectMocks;
2import org.mockito.Mock;
3
4class CheckoutServiceTest {
5
6    @Mock
7    PaymentGateway gateway;
8
9    @Mock
10    OrderRepository repository;
11
12    @InjectMocks
13    CheckoutService service;
14}

Mockito will create CheckoutService and try to inject the available mocks into it using constructor injection first, then setter or field injection if needed.

That means service is usually a real object with mocked dependencies, not a mock itself.

See the Difference in a Full Example

java
1@ExtendWith(MockitoExtension.class)
2class CheckoutServiceTest {
3
4    @Mock
5    PaymentGateway gateway;
6
7    @Mock
8    OrderRepository repository;
9
10    @InjectMocks
11    CheckoutService service;
12
13    @Test
14    void placesOrderWhenChargeSucceeds() {
15        when(gateway.charge(100)).thenReturn(true);
16
17        boolean result = service.checkout(100);
18
19        assertTrue(result);
20        verify(repository).save(any());
21    }
22}

Here:

  • 'gateway is a mock'
  • 'repository is a mock'
  • 'service is the real class under test, constructed with those mocks'

That is the mental model you want to keep.

@InjectMocks Does Not Replace Good Test Design

Mockito injection is convenient, but it should not hide the class structure. If a service has too many dependencies, @InjectMocks may make the test compile while still leaving the design overly coupled.

In those cases, the annotation is not the problem. The object under test probably has too many responsibilities.

Prefer Constructor Injection in Production Code

Mockito works best when the production class uses constructor injection. That makes dependencies explicit and usually leads Mockito to inject them predictably.

Field injection can still work, but constructor-based design is clearer and easier to reason about in both production and test code.

Avoid Confusing @InjectMocks with @Spy

A frequent mistake is thinking @InjectMocks makes a partially mocked object. It does not. If you need a real object with some method interception, that is a different concept, usually involving @Spy.

@InjectMocks is about wiring dependencies, not about changing the nature of the subject under test.

Once that distinction is clear, test setup becomes much easier to read: mocks stand in for collaborators, while the injected object is the thing whose logic you are actually asserting.

That separation is the core reason Mockito provides both annotations instead of one generic test helper.

Common Pitfalls

  • Assuming @InjectMocks creates a mock instead of a real object with injected mocks.
  • Forgetting that @Mock objects need stubbing when default Mockito return values are not enough.
  • Using @InjectMocks to hide an over-coupled class with too many dependencies.
  • Relying on field injection patterns that make dependency wiring less explicit.
  • Confusing @InjectMocks with @Spy or other Mockito annotations.

Summary

  • '@Mock creates mocked dependencies.'
  • '@InjectMocks creates the subject under test and injects mocks into it.'
  • The class marked with @InjectMocks is usually a real object, not a mock.
  • Constructor injection makes Mockito wiring clearer and more reliable.
  • These annotations help test structure, but they do not fix poor class design.

Course illustration
Course illustration

All Rights Reserved.