In a @WebMvcTest, how do you provide the controller's service dependency, and what happens if you don't?
answer
- @MockitoBean replaces @MockBean (3.4+)
- missing bean → UnsatisfiedDependency/NoSuchBeanDefinition
- when/thenReturn to stub
- mock replaces real bean
- @MockitoSpyBean = partial
basics
~10 sAdd the missing dependency as a mock with @MockitoBean (older: @MockBean). Without it, the slice can't inject the controller's service and the context fails to start with a NoSuchBeanDefinitionException.
solid answer
~40 sThe MVC slice loads controllers but not @Service/@Repository beans, so a controller's collaborators are missing. You declare each one as a field annotated with @MockitoBean (Spring Framework 6.2 / Boot 3.4+; previously Spring Boot's @MockBean). This registers a Mockito mock in the test context and injects it into the controller; you then stub with Mockito's when(...).thenReturn(...) and verify interactions. If you omit it, Spring can't satisfy the controller's constructor dependency and startup fails with UnsatisfiedDependencyException / NoSuchBeanDefinitionException. @MockitoBean also replaces a matching real bean if one exists. Alternatives include importing a small @TestConfiguration that supplies stubs, but mocking is the idiomatic approach for a slice because the real collaborators are intentionally absent.
code
java · 18 lines@WebMvcTest(OrderController.class)
class OrderControllerTest {
@Autowired MockMvc mockMvc;
@MockitoBean OrderService orderService; // required collaborator
@Test
void notFoundWhenServiceThrows() throws Exception {
when(orderService.get(99L))
.thenThrow(new OrderNotFoundException(99L));
mockMvc.perform(get("/orders/99"))
.andExpect(status().isNotFound());
verify(orderService).get(99L);
}
}go deeper
Knows you must mock the service, roughly with @MockBean/@MockitoBean.
Knows the exact exception on omission, current @MockitoBean naming, and default mock return values.
Distinguishes mock vs spy vs test-config stub and when each is appropriate.
Considers the bean-override migration story and reset/isolation semantics across a large suite.
## The problem the mock solves `@WebMvcTest` builds a context containing your controller but **not** its downstream dependencies (`@Service`, `@Repository`, etc.). A typical controller is constructor-injected: ```java @RestController class UserController { private final UserService userService; UserController(UserService userService) { this.userService = userService; } } ``` Spring must find a `UserService` bean to build `UserController`. Since the service isn't loaded, the context can't be created and you get an **`UnsatisfiedDependencyException`** wrapping a **`NoSuchBeanDefinitionException`** during test startup. ## The fix: @MockitoBean Declare the collaborator as a mock: ```java @MockitoBean UserService userService; ``` `@MockitoBean` (from `org.springframework.test.context.bean.override.mockito`, added in **Spring Framework 6.2 / Spring Boot 3.4**) creates a Mockito mock, registers it as a bean, and injects it into the controller. It is the modern replacement for Spring Boot's **`@MockBean`**, which still works but is **deprecated** in 3.4+. If a real bean of that type already existed in the context, `@MockitoBean` **replaces** it. ## Stubbing and verifying With the mock in place you drive controller behavior: ```java when(userService.findById(1L)).thenReturn(new UserDto(1L, "Ada")); // ... perform request ... verify(userService).findById(1L); ``` By default an un-stubbed mock method returns Mockito defaults (null, empty collection, 0), which is a common source of surprise NPEs or empty JSON in tests. ## Related override annotations - **`@MockitoSpyBean`** (was `@SpyBean`): wraps a real bean so unstubbed calls hit the real implementation. - A **`@TestConfiguration`** with `@Bean` methods can supply hand-written stubs when you prefer real objects over mocks; import it via `@Import`. ## Gotchas - One mock per required collaborator — if a controller needs three services, all three must be provided or startup fails. - Narrowing with `@WebMvcTest(UserController.class)` avoids having to mock dependencies of unrelated controllers. - `@MockitoBean` fields no longer need to be `static` and work at class level; you can also place it on a nested config. - Resetting: Mockito mocks are reset between test methods automatically by Spring Boot's `MockitoTestExecutionListener`.
- What is the difference between @MockitoBean and @MockitoSpyBean?@MockitoBean creates a full mock whose methods return defaults unless stubbed; @MockitoSpyBean wraps a real bean so unstubbed methods execute the real code, and you selectively override behavior.
- Why was @MockBean deprecated?Spring Framework 6.2 introduced a first-class 'bean override' mechanism (@MockitoBean/@MockitoSpyBean) in spring-test itself, so Spring Boot's @MockBean/@SpyBean were deprecated in favor of the framework-level annotations.
saying these in an interview costs you the question
- Saying you can @Autowired the real service in a @WebMvcTest without extra config
- Thinking the context still starts fine without providing the dependency
- Believing an unstubbed mock returns the real value rather than a Mockito default