0
0
Spring Bootframework~15 mins

@WebMvcTest for controller testing in Spring Boot - Deep Dive

Choose your learning style9 modes available
Overview - @WebMvcTest for controller testing
What is it?
@WebMvcTest is a special testing annotation in Spring Boot used to test only the web layer of your application, especially controllers. It loads only the parts needed to test web requests and responses, without starting the full application. This makes tests faster and focused on how your controllers handle HTTP calls.
Why it matters
Without @WebMvcTest, testing controllers often requires starting the entire application context, which is slow and can hide problems specific to the web layer. @WebMvcTest solves this by isolating controller tests, helping developers quickly find and fix issues in request handling and response formatting. This leads to faster development and more reliable web applications.
Where it fits
Before learning @WebMvcTest, you should understand basic Spring Boot applications and how controllers work. After mastering @WebMvcTest, you can explore full integration testing with @SpringBootTest and testing other layers like services and repositories.
Mental Model
Core Idea
@WebMvcTest creates a small, focused Spring environment that loads only the web layer to test controllers without starting the full application.
Think of it like...
Imagine testing a car's steering wheel by removing the engine and other parts, so you can focus only on how the steering wheel turns the wheels without distractions.
┌─────────────────────────────┐
│ Full Spring Boot Application │
│ ┌───────────────┐           │
│ │ Controllers   │           │
│ │ Services      │           │
│ │ Repositories  │           │
│ └───────────────┘           │
└────────────┬────────────────┘
             │
             ▼
┌─────────────────────────────┐
│ @WebMvcTest Environment      │
│ ┌───────────────┐           │
│ │ Controllers   │           │
│ └───────────────┘           │
│ (No Services or Repos)       │
└─────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Spring Controllers
🤔
Concept: Learn what controllers do in a Spring Boot app and how they handle HTTP requests.
Controllers are classes annotated with @RestController or @Controller that receive HTTP requests, process them, and return responses. They map URLs to methods using annotations like @GetMapping or @PostMapping.
Result
You know how a controller method is called when a user visits a URL or sends data.
Understanding controllers is essential because @WebMvcTest focuses on testing exactly these classes.
2
FoundationBasics of Spring Boot Testing
🤔
Concept: Learn how Spring Boot supports testing with annotations and test runners.
Spring Boot uses JUnit and annotations like @SpringBootTest to load the application context for tests. This loads all beans and configurations, which can be slow for simple tests.
Result
You understand the difference between full application tests and focused tests.
Knowing the cost of full context loading motivates using lighter test slices like @WebMvcTest.
3
IntermediateIntroducing @WebMvcTest Annotation
🤔Before reading on: do you think @WebMvcTest loads the entire Spring context or only parts? Commit to your answer.
Concept: @WebMvcTest loads only the web layer beans, mainly controllers, for focused testing.
When you annotate a test class with @WebMvcTest, Spring Boot creates a minimal context with only controllers and related web components like filters and converters. It excludes services, repositories, and other beans unless explicitly included.
Result
Tests run faster and focus only on controller behavior and HTTP interactions.
Understanding that @WebMvcTest isolates the web layer helps you write faster, more focused tests that catch web-specific bugs.
4
IntermediateUsing MockMvc for HTTP Testing
🤔Before reading on: do you think MockMvc sends real HTTP requests or simulates them inside the test? Commit to your answer.
Concept: MockMvc simulates HTTP requests and responses without a real server, allowing controller testing in isolation.
MockMvc is a Spring testing tool that lets you perform HTTP calls like GET or POST to controller endpoints inside your test code. It checks the response status, headers, and body without starting a web server.
Result
You can test controller endpoints quickly and verify their behavior precisely.
Knowing MockMvc simulates requests internally means you get fast tests without network overhead or server startup.
5
IntermediateConfiguring @WebMvcTest with Dependencies
🤔Before reading on: do you think @WebMvcTest automatically injects service beans used by controllers? Commit to your answer.
Concept: @WebMvcTest does not load service or repository beans, so you must mock them manually for controller dependencies.
Controllers often depend on services. Since @WebMvcTest excludes these beans, you use @MockBean to create fake versions. This lets you control their behavior during tests without loading real implementations.
Result
Your controller tests remain isolated and predictable, focusing only on web logic.
Understanding the need to mock dependencies prevents test failures and keeps tests focused on the controller layer.
6
AdvancedTesting Controller Advice and Filters
🤔Before reading on: do you think @WebMvcTest includes global exception handlers and filters by default? Commit to your answer.
Concept: @WebMvcTest can include controller advice and filters, but sometimes requires explicit configuration.
Controller advice classes annotated with @ControllerAdvice handle exceptions globally. Filters modify requests or responses. @WebMvcTest loads these if they are in the same slice, but you may need to import or mock them explicitly for full coverage.
Result
You can test how your controllers behave with global error handling and request filters applied.
Knowing how to include advice and filters in @WebMvcTest ensures your tests cover real-world controller behavior.
7
ExpertLimitations and Internals of @WebMvcTest
🤔Before reading on: do you think @WebMvcTest starts an embedded server or uses real network ports? Commit to your answer.
Concept: @WebMvcTest does not start a real server; it uses MockMvc to simulate requests inside the test context.
Internally, @WebMvcTest creates a minimal Spring context with DispatcherServlet and web infrastructure but no embedded server. MockMvc sends requests directly to this context. This design speeds tests but means some server-level features are not tested. Also, beans outside the web layer are excluded unless mocked.
Result
You understand why some integration issues may not appear in @WebMvcTest and when to use full integration tests.
Knowing the internal mechanics helps you choose the right test type and avoid false confidence from incomplete tests.
Under the Hood
@WebMvcTest triggers Spring Boot's test slice mechanism to load only web-related beans like controllers, Jackson converters, and Spring MVC infrastructure. It configures a DispatcherServlet in a test context without starting an actual web server. MockMvc sends simulated HTTP requests directly to this DispatcherServlet, bypassing network layers. Service and repository beans are excluded unless explicitly mocked, keeping the context lightweight.
Why designed this way?
Spring Boot designed @WebMvcTest to speed up controller testing by avoiding the overhead of loading the full application context and starting a server. This focused approach helps developers quickly test web layer logic and HTTP interactions. Alternatives like @SpringBootTest load everything, which is slower and less focused. The tradeoff is less coverage of full integration scenarios, but faster feedback for web logic.
┌─────────────────────────────┐
│ Test Class with @WebMvcTest │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│ Spring Test Context          │
│ ┌─────────────────────────┐ │
│ │ DispatcherServlet       │ │
│ │ Controllers             │ │
│ │ Jackson Converters      │ │
│ │ Filters & Advice        │ │
│ └─────────────────────────┘ │
│ (No Services or Repos)       │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│ MockMvc Simulated Requests   │
│ (No real HTTP server)        │
└─────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does @WebMvcTest load service beans automatically? Commit yes or no.
Common Belief:@WebMvcTest loads all beans including services and repositories automatically.
Tap to reveal reality
Reality:@WebMvcTest loads only web layer beans like controllers; services and repositories must be mocked manually.
Why it matters:Assuming services are loaded causes NullPointerExceptions or test failures, confusing beginners and wasting debugging time.
Quick: Does @WebMvcTest start a real web server? Commit yes or no.
Common Belief:@WebMvcTest starts an embedded server to test controllers with real HTTP calls.
Tap to reveal reality
Reality:@WebMvcTest uses MockMvc to simulate HTTP requests internally without starting a real server or using network ports.
Why it matters:Expecting a real server leads to confusion about test speed and inability to test server-level features like port conflicts.
Quick: Can @WebMvcTest test full application behavior including database? Commit yes or no.
Common Belief:@WebMvcTest is suitable for full integration tests including database and service layers.
Tap to reveal reality
Reality:@WebMvcTest is only for web layer testing; full integration tests require @SpringBootTest or similar annotations.
Why it matters:Misusing @WebMvcTest for full integration leads to incomplete tests and missed bugs in other layers.
Quick: Does @WebMvcTest automatically include global exception handlers? Commit yes or no.
Common Belief:All global controller advice and filters are always included in @WebMvcTest tests.
Tap to reveal reality
Reality:Some controller advice and filters may need explicit import or mocking to be active in @WebMvcTest.
Why it matters:Missing advice or filters in tests can hide bugs in error handling or request processing.
Expert Zone
1
MockMvc can be customized with filters and interceptors to mimic production behavior more closely within @WebMvcTest.
2
Using @Import or @ContextConfiguration allows adding specific beans to the @WebMvcTest slice when needed without loading the full context.
3
The test slice excludes security auto-configuration by default; you must explicitly configure security components to test secured endpoints.
When NOT to use
@WebMvcTest is not suitable when you need to test service logic, database interactions, or full application integration. Use @SpringBootTest or dedicated slice tests like @DataJpaTest for those layers instead.
Production Patterns
In real projects, @WebMvcTest is used for fast feedback on controller logic and HTTP contract correctness. Teams combine it with @SpringBootTest for end-to-end tests. MockBean is heavily used to isolate controllers from services. Tests often verify JSON structure, HTTP status codes, and headers using MockMvc.
Connections
Unit Testing
Builds-on
Understanding @WebMvcTest helps bridge unit testing and integration testing by focusing on a specific application layer, improving test granularity.
Microservices Architecture
Builds-on
In microservices, testing controllers in isolation with @WebMvcTest ensures each service's API behaves correctly before integration, supporting reliable distributed systems.
Network Protocol Simulation
Same pattern
MockMvc simulates HTTP requests internally like network protocol simulators in other fields, showing how complex external interactions can be tested without real network overhead.
Common Pitfalls
#1Forgetting to mock service dependencies causes test failures.
Wrong approach:@WebMvcTest(MyController.class) class MyControllerTest { @Autowired private MockMvc mockMvc; @Test void testEndpoint() throws Exception { mockMvc.perform(get("/api/data")) .andExpect(status().isOk()); } }
Correct approach:@WebMvcTest(MyController.class) class MyControllerTest { @Autowired private MockMvc mockMvc; @MockBean private MyService myService; @Test void testEndpoint() throws Exception { when(myService.getData()).thenReturn("mocked data"); mockMvc.perform(get("/api/data")) .andExpect(status().isOk()) .andExpect(content().string("mocked data")); } }
Root cause:Misunderstanding that @WebMvcTest excludes service beans and requires manual mocking.
#2Expecting @WebMvcTest to start a real server slows down tests unnecessarily.
Wrong approach:@WebMvcTest class ControllerTest { @Autowired private TestRestTemplate restTemplate; @Test void test() { ResponseEntity response = restTemplate.getForEntity("http://localhost/api", String.class); assertEquals(HttpStatus.OK, response.getStatusCode()); } }
Correct approach:@WebMvcTest class ControllerTest { @Autowired private MockMvc mockMvc; @Test void test() throws Exception { mockMvc.perform(get("/api")) .andExpect(status().isOk()); } }
Root cause:Confusing @WebMvcTest with full server tests and using TestRestTemplate which requires a running server.
#3Not including controller advice leads to missing error handling tests.
Wrong approach:@WebMvcTest(MyController.class) class MyControllerTest { @Autowired private MockMvc mockMvc; @Test void testError() throws Exception { mockMvc.perform(get("/api/error")) .andExpect(status().isInternalServerError()); } }
Correct approach:@WebMvcTest(controllers = MyController.class) @Import(GlobalExceptionHandler.class) class MyControllerTest { @Autowired private MockMvc mockMvc; @Test void testError() throws Exception { mockMvc.perform(get("/api/error")) .andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.message").value("Error occurred")); } }
Root cause:Assuming controller advice is automatically included in @WebMvcTest when it may require explicit import.
Key Takeaways
@WebMvcTest is a focused Spring Boot test annotation that loads only the web layer, mainly controllers, for fast and isolated HTTP request testing.
It uses MockMvc to simulate HTTP calls internally without starting a real web server, making tests quick and reliable.
Service and repository beans are excluded by default and must be mocked manually to avoid test failures.
Including controller advice and filters may require explicit configuration to fully test controller behavior.
Understanding @WebMvcTest internals helps choose the right testing approach and avoid common pitfalls in Spring Boot web testing.