Manual Mock Injection Without @InjectMocks | Java Fresher
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
To manually inject mocks without at-InjectMocks, you create the test subject yourself in the at-BeforeEach method by calling its constructor with the mocks as arguments.
mock calls. Then, in setUp, you instantiate the service with a plain constructor call, passing the mocks explicitly.
For example, if I'm testing OrderService, I'd create the paymentGateway and inventoryRepo mocks, then do orderService equals new OrderService with those mocks as parameters. This approach gives you complete control and makes the wiring obvious. If you pass the wrong type or forget a dependency, the compiler catches it immediately — you don't have to wait for a runtime NPE.
Manual injection is especially useful when you need different configurations of the same service across tests. Maybe one test needs the service with an email sender, another without. With manual construction, you just create two different instances in the respective test methods.
It's a few extra lines of code, but you get zero ambiguity and instant feedback. I still use at-Mock annotations for creating the mocks themselves because MockitoExtension handles cleanup automatically. Manual injection only replaces the at-InjectMocks step.
This pattern is common in teams that value explicitness over annotation magic.
Manual Mock Injection Without @InjectMocks | Java Fresher
Direct Answer
Create the class under test manually in @BeforeEach, passing mocks as constructor arguments. This is explicit, debuggable, and fails loudly if arguments don't match. Preferred for complex setups where @InjectMocks silent failure would be hard to debug.
Code Example
@ExtendWith(MockitoExtension.class)
class OrderServiceManualTest {
@Mock private PaymentGateway paymentGateway;
@Mock private InventoryRepository inventoryRepo;
@Mock private EmailSender emailSender;
private OrderService orderService;
@BeforeEach
void setUp() {
// Manual injection - explicit constructor call
orderService = new OrderService(paymentGateway, inventoryRepo, emailSender);
}
@Test
void shouldProcessOrderSuccessfully() {
var order = new Order(1L, List.of("item1", "item2"), 100.0);
when(inventoryRepo.reserve(order.getItems())).thenReturn(true);
when(paymentGateway.charge(order.getTotal())).thenReturn(true);
var result = orderService.processOrder(order);
assertThat(result).isTrue();
verify(emailSender).sendConfirmation(order);
}
@Test
void testWithDifferentConfig() {
// Easy to create alternate configuration
var testService = new OrderService(paymentGateway, inventoryRepo, null);
// test behavior when emailSender is absent
}
}
Common Mistakes & Pitfalls
- Recreating Mocks in @BeforeEach: Freshers sometimes call Mockito.mock() inside setUp() without using @Mock annotations, losing the automatic cleanup that MockitoExtension provides.
- Forgetting @ExtendWith: Even when manually constructing the service, you still need MockitoExtension to process @Mock annotations — without it, all mocks are null.
- Over-Using Manual Injection: Writing manual setup for every test when @InjectMocks would work fine — this adds boilerplate without benefit. Use manual injection when it actually solves a problem, not as a blanket rule.
Check your understanding
Answer these without looking back at the article.
- How do you inject mocks via setter in tests?
- What are the advantages of @InjectMocks over manual construction?
- How do you inject mocks for a class with a non-public constructor?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.