What is @WebMvcTest and what does it load (and not load) into the Spring context?
answer
- slice = web layer only
- controllers + MockMvc auto-configured
- no services/repos → @MockitoBean
- narrow with (Controller.class)
- fast, no DB, no port
basics
~10 s@WebMvcTest is a Spring Boot test annotation that starts only the web/MVC layer — your controllers plus MockMvc — without loading services, repositories, or the full application. It makes controller tests fast and focused.
solid answer
~40 s@WebMvcTest is a 'test slice' annotation from Spring Boot. Instead of starting the whole application context (like @SpringBootTest), it auto-configures only the Spring MVC infrastructure: your @Controller/@RestController beans, @ControllerAdvice, Filters, HandlerInterceptors, Jackson JSON converters, and an auto-configured MockMvc to send fake HTTP requests. It deliberately leaves out @Service, @Repository, @Component, and persistence/JPA beans. Because collaborators like services are absent, you must supply them with @MockitoBean (formerly @MockBean). This keeps the test tiny and fast — it exercises request mapping, validation, serialization, and error handling without touching a database or business logic. You typically narrow it further with @WebMvcTest(MyController.class) so only one controller loads.
code
java · 18 lines@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
MockMvc mockMvc; // auto-configured by the slice
@MockitoBean
UserService userService; // service isn't loaded — must be mocked
@Test
void returnsUser() throws Exception {
when(userService.findById(1L)).thenReturn(new UserDto(1L, "Ada"));
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Ada"));
}
}go deeper
Should know it loads only controllers + MockMvc and that services must be mocked.
Should list the concrete bean types loaded (@ControllerAdvice, filters, converters) and know @MockitoBean vs @MockBean naming.
Should explain slicing tradeoffs, security-on-classpath effects, and narrowing to one controller.
Should reason about when a slice is the wrong tool (integration boundaries) and test-suite performance strategy across slices.
## What it is `@WebMvcTest` is a Spring Boot **test slice** annotation (package `org.springframework.boot.test.autoconfigure.web.servlet`). A 'slice' means Spring Boot builds a **partial** application context containing only the beans relevant to one layer — here, the Spring MVC (web) layer — rather than the entire application. ## What gets loaded When you annotate a test class with `@WebMvcTest`, Spring Boot auto-configures: - **Controllers**: beans annotated with `@Controller` / `@RestController`. - **`@ControllerAdvice` / `@RestControllerAdvice`**: global exception handlers and model attributes. - **`Filter`s** and Spring MVC `HandlerInterceptor`s. - **`Converter` / `Formatter`** beans and `HttpMessageConverter`s (e.g. Jackson `MappingJackson2HttpMessageConverter` for JSON). - **`WebMvcConfigurer`** beans and Spring Security (if on the classpath, the security filter chain is applied). - An auto-configured **`MockMvc`** you inject to perform simulated HTTP requests — no real servlet container/port is started. ## What is NOT loaded Regular `@Component`, `@Service`, `@Repository` beans, `@Configuration` that isn't web-related, JPA/`DataSource`/`EntityManager`, and messaging infrastructure are all **excluded**. This is the whole point: the web layer is tested in isolation. ## Consequence: mock the collaborators Because the controller's dependencies (e.g. a `UserService`) are not in the context, the context would fail to start with a `NoSuchBeanDefinitionException` unless you provide a stand-in. You add `@MockitoBean UserService userService;` (Spring Boot 3.4+ name; earlier it was `@MockBean`). This registers a Mockito mock in the context and injects it into the controller. You then `when(...).thenReturn(...)` to stub responses. ## Narrowing scope `@WebMvcTest` with no argument loads **all** controllers in the application. Passing a class — `@WebMvcTest(UserController.class)` or `@WebMvcTest(controllers = UserController.class)` — restricts the slice to just that controller, so unrelated controllers (and their dependencies) don't force extra mocks. ## When to use it Use it to test **web-layer concerns**: URL/path mapping, request parameter binding, `@Valid` bean validation and the resulting 400s, JSON (de)serialization, status codes, headers, and exception-to-response mapping via `@ControllerAdvice`. Do **not** use it to test business logic (that belongs in plain unit tests of the service) or real persistence (use `@DataJpaTest` or `@SpringBootTest`). ## Gotchas - Forgetting `@MockitoBean` → context fails to start. - If Spring Security is on the classpath, endpoints may return 401/403 unexpectedly; add security test config or `@WithMockUser`. - It's a **servlet** slice; for WebFlux use `@WebFluxTest` instead.
- Why does the context fail if you forget to mock the service?The controller declares the service as a dependency, but the slice doesn't load @Service beans, so Spring can't satisfy the injection — it throws NoSuchBeanDefinitionException / UnsatisfiedDependencyException at context startup unless you provide a @MockitoBean.
- How is @WebMvcTest different from @SpringBootTest?@SpringBootTest starts the full application context (all beans, real services, DB) and is slower; @WebMvcTest loads only the MVC layer with mocked collaborators, so it's a focused, fast web-layer test.
saying these in an interview costs you the question
- Thinking @WebMvcTest loads services and repositories
- Believing it starts a real HTTP server on a port
- Confusing it with @DataJpaTest (persistence slice)
- Assuming a real database is available