Discover how to test your web controllers quickly without starting your whole app!
Why @WebMvcTest for controller testing in Spring Boot? - Purpose & Use Cases
Imagine writing tests for your web controllers by starting the whole application and manually sending HTTP requests to check responses.
This approach is slow, requires a full app context, and makes it hard to isolate controller logic from other parts like services or databases.
@WebMvcTest lets you test only the web layer, loading just the controller and related components, so tests run fast and focus on controller behavior.
start full app context send HTTP request check response
@WebMvcTest(MyController.class) mockMvc.perform(get("/path")) .andExpect(status().isOk())
It enables fast, focused tests that verify your controller's behavior without the overhead of starting the entire application.
When adding a new API endpoint, you can quickly write a @WebMvcTest to check if it returns the right status and JSON without waiting for the full app to start.
Manual full app tests are slow and complex.
@WebMvcTest isolates controller testing for speed and focus.
It helps catch web layer issues early and easily.
Practice
@WebMvcTest in Spring Boot testing?Solution
Step 1: Understand the role of @WebMvcTest
@WebMvcTest is designed to load only the Spring MVC components like controllers, filters, and related configurations, not the full app context.Step 2: Compare with other test annotations
Unlike @SpringBootTest which loads the full context, @WebMvcTest focuses on controller layer for fast, isolated web tests.Final Answer:
To test only the web layer (controllers) without starting the full application context -> Option AQuick Check:
@WebMvcTest = controller-only test [OK]
- Thinking @WebMvcTest loads full Spring context
- Confusing @WebMvcTest with @SpringBootTest
- Assuming it tests service or repository layers
@WebMvcTest for a controller named UserController?Solution
Step 1: Check @WebMvcTest syntax for specifying controllers
The correct syntax to specify which controllers to test is using the 'controllers' attribute, e.g., @WebMvcTest(controllers = UserController.class).Step 2: Eliminate incorrect options
@WebMvcTest(UserController.class) public class UserControllerTest {} misses 'controllers =' keyword, @WebMvcTest public class UserControllerTest {} does not specify controller, @WebMvcTest(services = UserController.class) public class UserControllerTest {} wrongly uses 'services' attribute.Final Answer:
@WebMvcTest(controllers = UserController.class) public class UserControllerTest {} -> Option DQuick Check:
@WebMvcTest(controllers = ...) is correct syntax [OK]
- Omitting 'controllers =' keyword
- Using 'services =' instead of 'controllers ='
- Not specifying any controller class
@WebMvcTest and MockMvc, what will be the HTTP status returned by the test?@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHello() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().isOk());
}
}
@RestController
class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "Hello World";
}
}Solution
Step 1: Analyze the controller mapping
The HelloController has a GET mapping for '/hello' that returns a string "Hello World".Step 2: Understand MockMvc test behavior
The test performs a GET request to '/hello' and expects status 200 OK, which matches the controller's response.Final Answer:
200 OK -> Option BQuick Check:
GET /hello returns 200 OK [OK]
- Expecting 404 when mapping exists
- Confusing status codes for successful GET
- Missing controller in @WebMvcTest causing 404
@WebMvcTest test class that causes the test to fail with a NullPointerException.@WebMvcTest(controllers = UserController.class)
public class UserControllerTest {
private MockMvc mockMvc;
@Test
public void testGetUser() throws Exception {
mockMvc.perform(get("/user/1"))
.andExpect(status().isOk());
}
}Solution
Step 1: Check MockMvc initialization
The MockMvc field is declared but not initialized or injected, so it remains null causing NullPointerException.Step 2: Fix by adding @Autowired
Adding @Autowired on the MockMvc field lets Spring inject the mockMvc instance for testing.Final Answer:
Missing @Autowired annotation on MockMvc field -> Option AQuick Check:
MockMvc must be @Autowired to avoid null [OK]
- Forgetting @Autowired on MockMvc
- Assuming MockMvc is auto-initialized without annotation
- Misnaming test methods without @Test
OrderController that depends on a service OrderService. Using @WebMvcTest, how can you provide a mock OrderService to the controller during testing?Solution
Step 1: Understand @WebMvcTest scope
@WebMvcTest loads only web layer, so service beans are not loaded automatically.Step 2: Use @MockBean to provide mock dependencies
Annotating OrderService with @MockBean in the test class creates and injects a mock into the controller.Final Answer:
Use @MockBean on OrderService field in the test class to inject a mock -> Option CQuick Check:
@MockBean mocks service dependencies in @WebMvcTest [OK]
- Trying to @Autowired real service in @WebMvcTest
- Not mocking service causing NoSuchBeanDefinitionException
- Switching to @SpringBootTest unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
