Constructor vs Field Injection in @InjectMocks
Fast recall
Quick revision
Core answer
@InjectMocks, Mockito considers constructor injection first and chooses the largest constructor, resolving mock arguments by type and possibly passing null for unresolved non-mockable parameters. If construction succeeds, it stops there. Otherwise it can try property/setter injection and then field injection on a usable instance. In production code, required constructor injection is usually clearer because callers must supply dependencies and tests can instantiate the class explicitly.Interview-ready guide
Interview answer
With @InjectMocks, Mockito first considers constructor injection. It selects the largest constructor and tries to resolve arguments from the mocks and spies declared in the test. An unresolved non-mockable argument may be passed as null. If the constructor successfully creates the object, Mockito does not then fill remaining setters or fields.
When constructor injection is not used, Mockito can try property or setter injection and finally field injection. These strategies mainly match by type and may use names when types are ambiguous.
I prefer required constructor injection in production code because it makes dependencies part of the class contract and allows final fields. In a unit test I can write new OrderService(orderRepository, paymentGateway), so the compiler checks the wiring. That design benefit is more important than relying on Mockito's strategy order.
Constructor vs Field Injection in @InjectMocks
Direct Answer
For @InjectMocks, Mockito considers constructor injection first and chooses the largest constructor, resolving mock arguments by type and possibly passing null for unresolved non-mockable parameters. If construction succeeds, it stops there. Otherwise it can try property/setter injection and then field injection on a usable instance. In production code, required constructor injection is usually clearer because callers must supply dependencies and tests can instantiate the class explicitly.
Code Example
class NotificationService {
private final EmailSender emailSender;
private final SmsSender smsSender;
private PushNotifier pushNotifier; // optional, set via setter
// Constructor injection - Mockito tries this first
public NotificationService(EmailSender emailSender, SmsSender smsSender) {
this.emailSender = emailSender;
this.smsSender = smsSender;
}
// Setter injection - Mockito tries this second if no matching constructor
public void setPushNotifier(PushNotifier pushNotifier) {
this.pushNotifier = pushNotifier;
}
public void notifyUser(String message) {
emailSender.send(message);
smsSender.send(message);
if (pushNotifier != null) pushNotifier.send(message);
}
}
@ExtendWith(MockitoExtension.class)
class NotificationServiceTest {
@Mock EmailSender emailSender;
@Mock SmsSender smsSender;
@Mock PushNotifier pushNotifier;
@InjectMocks NotificationService service; // constructor + setter injection
@Test
void shouldSendAllNotifications() {
service.notifyUser("Test message");
verify(emailSender).send("Test message");
verify(pushNotifier).send("Test message"); // injected via setter
}
}
Common Mistakes & Pitfalls
- Assuming Field Injection is First: Freshers think Mockito directly assigns mocks to fields because that's what Spring does with @Autowired field injection. Mockito actually tries constructors first.
- Multiple Constructors Without Clarity: Having several constructors without understanding that Mockito picks the largest one that matches available mocks, which can inject unintended configurations.
- Mixing Injection Styles Randomly: Using constructor injection for some dependencies and field injection for others without a clear pattern, making tests unpredictable.
- Not Marking Optional Dependencies: Declaring all dependencies as constructor parameters, even optional ones, forcing test setup to provide mocks for features not relevant to the test.
Check your understanding
Answer these without looking back at the article.
- What happens if the class has multiple constructors?
- How does constructor injection improve testability beyond just Mockito?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.