使用`MockMvc`额外的补充和高级用法
1. 处理路径变量的GET请求
假设你的控制器有一个带路径变量的`GET`接口:
```java @GetMapping("/users/{id}") public ResponseEntity<User> getUserById(@PathVariable Long id) { // 假设通过ID获取用户信息 User user = new User(id, "John", "Doe"); return ResponseEntity.ok(user); } ```
测试这个接口的方法如下:
```java @Test public void testGetUserById() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/users/{id}", 1L)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(1)) .andExpect(jsonPath("$.firstName").value("John")) .andExpect(jsonPath("$.lastName").value("Doe")); } ```
2. 处理带Header的请求
假设你的控制器需要处理带特定`Header`的请求:
```java @PostMapping("/secured") public ResponseEntity<String> securedEndpoint(@RequestHeader("Authorization") String authorizationHeader) { if ("Bearer valid_token".equals(authorizationHeader)) { return ResponseEntity.ok("Access granted"); } else { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Access denied"); } } ```
测试这个接口的方法如下:
```java @Test public void testSecuredEndpointWithValidToken() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/api/secured") .header("Authorization", "Bearer valid_token")) .andExpect(status().isOk()) .andExpect(content().string("Access granted")); } @Test public void testSecuredEndpointWithInvalidToken() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/api/secured") .header("Authorization", "Bearer invalid_token")) .andExpect(status().isUnauthorized()) .andExpect(content().string("Access denied")); } ```
3. 处理文件上传的POST请求
假设你的控制器需要处理文件上传:
```java @PostMapping("/upload") public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) { // 假设处理文件上传逻辑 return ResponseEntity.ok("File uploaded successfully: " + file.getOriginalFilename()); } ```
测试文件上传的方法如下:
```java @Test public void testHandleFileUpload() throws Exception { MockMultipartFile file = new MockMultipartFile("file", "test.txt", "text/plain", "Spring Framework".getBytes()); mockMvc.perform(MockMvcRequestBuilders.multipart("/api/upload").file(file)) .andExpect(status().isOk()) .andExpect(content().string("File uploaded successfully: test.txt")); } ```
4. 验证请求体中的JSON字段
假设你有一个需要验证请求体中JSON字段的`POST`接口:
```java @PostMapping("/createOrder") public ResponseEntity<Order> createOrder(@RequestBody Order order) { // 假设有一个Order类,并且返回创建订单对象 return ResponseEntity.ok(order); } ```
假设`Order`类如下:
```java public class Order { private Long id; private String product; private Integer quantity; // getters and setters } ```
测试这个接口的方法如下:
```java @Test public void testCreateOrder() throws Exception { String orderJson = "{\"id\":1, \"product\":\"Laptop\", \"quantity\":2}"; mockMvc.perform(MockMvcRequestBuilders.post("/api/createOrder") .content(orderJson) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(1)) .andExpect(jsonPath("$.product").value("Laptop")) .andExpect(jsonPath("$.quantity").value(2)); } ```
5. 测试异常处理
假设你的控制器有全局异常处理:
```java @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<String> handleResourceNotFound(ResourceNotFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); } } ```
在控制器中抛出`ResourceNotFoundException`:
```java @GetMapping("/resource/{id}") public ResponseEntity<String> getResource(@PathVariable Long id) { throw new ResourceNotFoundException("Resource not found with id " + id); } ```
测试异常处理的方法如下:
```java @Test public void testResourceNotFoundException() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/resource/{id}", 1L)) .andExpect(status().isNotFound()) .andExpect(content().string("Resource not found with id 1")); } ```
6. 完整的测试类示例
以下是包含所有上述测试的完整测试类示例:
```java @RunWith(SpringRunner.class) @WebMvcTest(YourController.class) public class YourControllerTest { @Autowired private MockMvc mockMvc; @Test public void testGreetWithSingleParam() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/greet") .param("name", "John")) .andExpect(status().isOk()) .andExpect(content().string("Hello, John")); } @Test public void testWelcomeWithMultipleParams() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/welcome") .param("firstName", "John") .param("lastName", "Doe")) .andExpect(status().isOk()) .andExpect(content().string("Welcome, John Doe")); } @Test public void testEchoWithSingleParam() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/api/echo") .content("Hello, World!") .contentType(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) .andExpect(content().string("Hello, World!")); } @Test public void testCreateUserWithMultipleParams() throws Exception { String userJson = "{\"firstName\":\"John\", \"lastName\":\"Doe\"}"; mockMvc.perform(MockMvcRequestBuilders.post("/api/createUser") .content(userJson) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.firstName").value("John")) .andExpect(jsonPath("$.lastName").value("Doe")); } @Test public void testGetUserById() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/users/{id}", 1L)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(1)) .andExpect(jsonPath("$.firstName").value("John")) .andExpect(jsonPath("$.lastName").value("Doe")); } @Test public void testSecuredEndpointWithValidToken() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/api/secured") .header("Authorization", "Bearer valid_token")) .andExpect(status().isOk()) .andExpect(content().string("Access granted")); } @Test public void testSecuredEndpointWithInvalidToken() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/api/secured") .header("Authorization", "Bearer invalid_token")) .andExpect(status().isUnauthorized()) .andExpect(content().string("Access denied")); } @Test public void testHandleFileUpload() throws Exception { MockMultipartFile file = new MockMultipartFile("file", "test.txt", "text/plain", "Spring Framework".getBytes()); mockMvc.perform(MockMvcRequestBuilders.multipart("/api/upload").file(file)) .andExpect(status().isOk()) .andExpect(content().string("File uploaded successfully: test.txt")); } @Test public void testCreateOrder() throws Exception { String orderJson = "{\"id\":1, \"product\":\"Laptop\", \"quantity\":2}"; mockMvc.perform(MockMvcRequestBuilders.post("/api/createOrder") .content(orderJson) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(1)) .andExpect(jsonPath("$.product").value("Laptop")) .andExpect(jsonPath("$.quantity").value(2)); } @Test public void testResourceNotFoundException() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/api/resource/{id}", 1L)) .andExpect(status().isNotFound()) .andExpect(content().string("Resource not found with id 1")); } } ```
通过这些示例,我们可以更好地理解如何使用`MockMvc`来测试Spring Boot应用中的各种情况,包括路径变量、请求头、文件上传、JSON请求体验证以及异常处理。