🎯 The Ultimate Guide to @Mock
, @InjectMocks
and @MockBean
in Spring Boot Testing
✅ By the end, you’ll know exactly when to use each, how they work under the hood, and what you’re truly testing.
🚀 Why do we need mocks?
When writing unit tests, you want to test your business logic in isolation, without hitting:
- real databases
- HTTP calls
- or heavy Spring context.
Mocks allow us to fake out dependencies, so we focus purely on what the class itself does.
⚙ The three key annotations
Annotation | Where to use it | What it does |
---|---|---|
@Mock |
In pure unit tests | Creates a fake (mock) object of your dependency. |
@InjectMocks |
In pure unit tests | Creates an instance of your class under test and injects the mocks automatically. |
@MockBean |
In Spring Boot tests (@SpringBootTest ) |
Replaces a Spring Bean in the application context with a mock. |
🔍 The difference, with a story
👇 Example scenario
Imagine we have:
OrderService
that depends onOrderRepository
.OrderController
that depends onOrderService
.
OrderController → OrderService → OrderRepository
🧪 Unit testing OrderService
We want to test just the logic inside OrderService
, no Spring, no HTTP.
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private OrderRepository orderRepository; // creates a fake object
@InjectMocks
private OrderService orderService; // real service, gets mock injected
@Test
void testGetOrder() {
when(orderRepository.findById(1))
.thenReturn(Optional.of(new Order(1, "Laptop")));
Order result = orderService.getOrder(1);
assertEquals("Laptop", result.getName());
verify(orderRepository).findById(1);
}
}
✅ What exactly are we testing?
- That
OrderService
correctly callsorderRepository.findById()
- Returns the right order
- Nothing to do with Spring or HTTP.
🚀 Spring Boot test with @MockBean
Now we want to test that Spring wiring works, i.e.
OrderController
callsOrderService
OrderService
callsOrderRepository
but we still don’t want to hit a real DB.
@SpringBootTest
class OrderControllerTest {
@Autowired
private OrderController orderController; // real bean from Spring
@MockBean
private OrderRepository orderRepository; // replaces real bean with mock
@Test
void testGetOrder() {
when(orderRepository.findById(1))
.thenReturn(Optional.of(new Order(1, "Laptop")));
Order result = orderController.getOrder(1);
assertEquals("Laptop", result.getName());
verify(orderRepository).findById(1);
}
}
✅ What exactly are we testing?
- That Spring autowires everything properly.
- That controller → service → repository chain works.
🌐 Testing the HTTP endpoint
Finally, test the actual HTTP API, still with mocked repository.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class OrderControllerHttpTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private OrderRepository orderRepository;
@Test
void testGetOrderHttp() throws Exception {
when(orderRepository.findById(1))
.thenReturn(Optional.of(new Order(1, "Laptop")));
mockMvc.perform(get("/orders/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Laptop"));
}
}
✅ Now we’re testing:
- The entire Spring Boot stack
- JSON serialization
- Correct HTTP status codes.
📝 So when do I use what?
You want to test… | Use this | Why |
---|---|---|
Only class logic, very fast, no Spring | @Mock + @InjectMocks |
Let Mockito build your class & inject fakes |
Wiring inside Spring context, no HTTP | @SpringBootTest + @MockBean |
Spring loads beans & you replace dependencies |
The full HTTP REST endpoint | @SpringBootTest + @AutoConfigureMockMvc + @MockBean |
Test full HTTP layer with JSON |
🔍 Under the hood: how does @InjectMocks
work?
@InjectMocks
private OrderService orderService;
@Mock
private OrderRepository orderRepository;
Mockito sees that OrderService
needs OrderRepository
and automatically injects it, either via constructor or field. ✅
🥇 Key takeaways
- ✅ Use
@Mock
+@InjectMocks
for fast, isolated Java logic tests, no Spring needed. - ✅ Use
@MockBean
to replace beans in Spring context when testing controllers or services inside a Spring Boot app. - ✅ Always clearly decide: “Am I testing pure logic or Spring wiring or HTTP layer?”
🎉 Hope this clears it up once and for all.
If you liked it, drop a ⭐ or share it with your team — so everyone stops being confused by @Mock
, @InjectMocks
, and @MockBean
forever!
Leave a Reply