Spring Boot @WebMvcTest Example

1. Introduction

In Spring Boot, @WebMvcTest is specifically designed for testing Spring MVC controllers. This annotation creates a mock servlet environment and focuses only on the web layer, ignoring the server and the context.

Key Points:

1. @WebMvcTest is used for controller layer tests and does not load the full application context.

2. It auto-configures MockMvc for sending simulated HTTP requests to the controller.

3. Combined with @MockBean, it allows for mocking dependencies required by the controllers.

2. Implementation Steps

1. Annotate a test class with @WebMvcTest, specifying the controller you want to test.

2. Autowire MockMvc into the test class.

3. Mock any required service layer dependencies using @MockBean.

4. Write test methods using MockMvc to perform and verify web requests.

5. Run the test class using a testing framework like JUnit.

3. Implementation Example

Here is the complete code that demonstrates the usage of @WebMvcTest annotation:
// Assume we have a UserController in a typical Spring Boot application

@RestController
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/user/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return ResponseEntity.ok(user);
    }
}

// Service that the UserController depends on
@Service
public class UserService {
    public User getUserById(Long id) {
        // Service logic to get a user by ID
    }
}

// Test class
@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    public void getUser_ShouldReturnUser() throws Exception {
        User testUser = new User(1L, "Test User");
        Mockito.when(userService.getUserById(1L)).thenReturn(testUser);

        mockMvc.perform(MockMvcRequestBuilders.get("/user/1"))
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("Test User"));
    }
}

// Main application class for completeness
@SpringBootApplication
public class MySpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }
}

Output:

// The test console output should indicate that the test passed successfully
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 sec

Explanation:

1. The UserController class is a REST controller that has a dependency on UserService.

2. UserControllerTest is marked with @WebMvcTest(UserController.class) indicating that the test context should only include the MVC infrastructure related to UserController.

3. MockMvc is used within UserControllerTest to perform a mock HTTP GET request to /user/1.

4. @MockBean is used to create a mock of UserService to ensure the controller can call getUserById without needing the actual service layer.

5. The getUser_ShouldReturnUser test method defines behavior for the mock service, performs the mock MVC call, and then asserts the response.

6. The main application class MySpringBootApplication is annotated with @SpringBootApplication, which is the entry point of the Spring Boot application but is not involved in the test.

7. The output shows the result of the test execution, verifying that UserController.getUser method behaves as expected when retrieving a user by ID.


Comments