skip to content

@WebMvcTest

@WebMvcTest loads controllers, advice, filters and converters with MockMvc wired, and nothing below the web layer — so collaborators must be mocked. Interviewers ask what this test can and cannot prove about your endpoint.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is @WebMvcTest and what does it load (and not load) into the Spring context?

level: juniorimportance: must knowfreq 82%

answer

  1. slice = web layer only
  2. controllers + MockMvc auto-configured
  3. no services/repos → @MockitoBean
  4. narrow with (Controller.class)
  5. 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
java
@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

for a junior

Should know it loads only controllers + MockMvc and that services must be mocked.

for a middle

Should list the concrete bean types loaded (@ControllerAdvice, filters, converters) and know @MockitoBean vs @MockBean naming.

for a senior

Should explain slicing tradeoffs, security-on-classpath effects, and narrowing to one controller.

for a principal

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

context

open as a page

In a @WebMvcTest, how do you provide the controller's service dependency, and what happens if you don't?

level: middleimportance: must knowfreq 74%

basics

~10 s

Add 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.

open as a page

With Spring Security on the classpath, a @WebMvcTest returns 401/403 unexpectedly. Why, and how do you handle it correctly?

level: seniorimportance: should knowfreq 55%

basics

~20 s

@WebMvcTest applies your Spring Security filter chain, so unauthenticated MockMvc requests get blocked. Fix it by authenticating the test request — e.g. @WithMockUser or SecurityMockMvcRequestPostProcessors — or by importing your security config, not by disabling security.

open as a page

When would you choose @WebMvcTest over @SpringBootTest, and what are the tradeoffs?

level: seniorimportance: should knowfreq 68%

basics

~10 s

Use @WebMvcTest for fast, isolated web-layer tests (routing, validation, JSON, error handling) with mocked services. Use @SpringBootTest when you need the full context — real service/repository wiring or true end-to-end integration.

open as a page

How does the @WebMvcTest slice actually decide which beans and auto-configurations to include, and how would you customize it?

level: principalimportance: nice to knowfreq 34%

basics

~10 s

@WebMvcTest is meta-annotated to restrict component scanning to web-layer stereotypes via a TypeExcludeFilter, and to enable only web-related auto-configurations listed in spring.factories/AutoConfiguration.imports. You customize it with controllers=, @Import, @AutoConfigure* annotations, or excludeAutoConfiguration.

open as a page