How to Use @WebMvcTest in Spring Boot for Controller Testing
Use
@WebMvcTest in Spring Boot to test only the web layer (controllers) without starting the full application context. It loads only the MVC components needed for controller tests, making tests faster and more focused.Syntax
The @WebMvcTest annotation is placed on a test class to load only Spring MVC components such as controllers, filters, and related configurations. You specify the controller class to test as a parameter.
It disables full auto-configuration and limits the context to web layer beans only.
java
@WebMvcTest(YourController.class) public class YourControllerTest { @Autowired private MockMvc mockMvc; // test methods here }
Example
This example shows how to test a simple Spring Boot controller using @WebMvcTest. It verifies that a GET request to /hello returns the expected response.
java
package com.example.demo; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(HelloController.class) public class HelloControllerTest { @Autowired private MockMvc mockMvc; @Test public void testHello() throws Exception { mockMvc.perform(get("/hello")) .andExpect(status().isOk()) .andExpect(content().string("Hello, Spring Boot!")); } } // Controller class package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello, Spring Boot!"; } }
Output
Test passes with HTTP 200 OK and response body "Hello, Spring Boot!"
Common Pitfalls
- Not specifying the controller class in
@WebMvcTestcan load multiple controllers, making tests slower. - Trying to load service or repository beans will fail because
@WebMvcTestonly loads web layer beans. - For dependencies like services, use
@MockBeanto mock them in the test.
java
/* Wrong: Missing @MockBean for service dependency causes failure */ @WebMvcTest(UserController.class) public class UserControllerTest { @Autowired private MockMvc mockMvc; // UserService is not mocked, test will fail } /* Right: Mock service dependency */ @WebMvcTest(UserController.class) public class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; // Now test can run with mocked service }
Quick Reference
- @WebMvcTest(Controller.class): Loads only the specified controller and MVC components.
- MockMvc: Used to perform HTTP requests in tests.
- @MockBean: Mock dependencies like services for isolated controller tests.
- Does not load full Spring context or database layers.
Key Takeaways
Use @WebMvcTest to test only Spring MVC controllers without loading full context.
Specify the controller class in @WebMvcTest to limit loaded beans and speed up tests.
Mock service or repository dependencies with @MockBean to avoid context loading errors.
Use MockMvc to simulate HTTP requests and verify controller responses.
Avoid loading full application context for faster, focused web layer tests.