SpringMockMvc删除接口测试教程
时间:2025-07-24 10:03:34 382浏览 收藏
在文章实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Spring MockMvc 删除请求测试教程》,聊聊,希望可以帮助到正在努力赚钱的你。
在开发Spring RESTful API时,对控制器层进行单元测试是至关重要的环节。MockMvc作为Spring Test模块的核心工具,提供了强大的能力来模拟HTTP请求并验证控制器行为。然而,在测试涉及路径变量的DELETE请求时,开发者可能会遇到一些常见的陷阱,尤其是在处理“空”或“零值”ID的场景。
1. 理解MockMvc的URL模板与路径变量
Spring MockMvc在构建请求URI时,支持类似于String.format()的URL模板语法。这意味着,当控制器定义了一个带有路径变量的端点,例如@DeleteMapping("/{id}")时,MockMvc应该使用占位符来构建请求。
假设我们有一个WalletController,其删除方法如下:
@RestController @RequestMapping("api/wallet") @RequiredArgsConstructor @Validated public class WalletController { private final WalletService walletService; @DeleteMapping("/{id}") public ResponseEntitydeleteWalletById(@Valid @Min(1) @PathVariable Long id) { walletService.deleteWalletById(id); HttpHeaders headers = new HttpHeaders(); headers.add("message", "You have successfully completed the delete of a Wallet!"); return new ResponseEntity<>(headers, HttpStatus.OK); } }
注意@PathVariable Long id上的@Min(1)注解,它要求id的值必须大于或等于1。
正确使用URL模板
当我们需要测试一个特定的ID,例如123L时,正确的MockMvc调用方式是:
mockMvc.perform(delete("/api/wallet/{id}", 123L));
这里的{id}是一个占位符,123L是实际传入的值。MockMvc会将其解析为/api/wallet/123。
2. 测试零值ID的场景
针对上述控制器中的@Min(1)验证,如果我们尝试传入id = 0L,请求应该被控制器捕获并在验证阶段失败,返回400 Bad Request。
以下是测试零值ID的示例:
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.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.mockito.Mockito.verifyNoInteractions; @WebMvcTest(WalletController.class) // 指定测试的控制器 class WalletControllerTest { @Autowired private MockMvc mockMvc; @MockBean private WalletService walletService; // 模拟服务层 @Test void shouldReturnBadRequestWhenWalletIdIsZeroDueToValidation() throws Exception { // Given Long id = 0L; // ID为0,违反@Min(1)约束 // When mockMvc.perform(delete("/api/wallet/{id}", id) .contentType(MediaType.APPLICATION_JSON)) // Then .andExpect(status().isBadRequest()); // 期望400 Bad Request // 验证服务层方法未被调用,因为请求在控制器验证阶段就被拒绝了 verifyNoInteractions(walletService); } }
在这个测试中,delete("/api/wallet/{id}", id)会生成/api/wallet/0这个URI。由于0不满足@Min(1)的条件,Spring的验证机制会拦截请求,并返回400 Bad Request,服务层方法不会被执行。
3. 处理“空”ID(空字符串路径)的场景
这是最容易引起混淆和错误的地方。当尝试用空字符串""作为路径变量的值时,例如delete("/api/wallet/{}", ""),MockMvc最终生成的URI将是/api/wallet/。
为什么这会导致问题?
- URI不匹配: 控制器定义的端点是@DeleteMapping("/{id}"),它期望在/api/wallet/后面跟着一个ID。而/api/wallet/(不带ID)是一个完全不同的URI。
- 请求路由失败: Spring的DispatcherServlet会尝试将DELETE /api/wallet/请求映射到相应的处理器。
- 如果应用程序中没有任何处理器映射到DELETE /api/wallet/,那么最常见的响应是404 Not Found。
- 如果应用程序中存在处理器映射到/api/wallet/,但只支持其他HTTP方法(例如@GetMapping("/api/wallet")),那么尝试用DELETE方法访问它将导致405 Method Not Allowed。
- 在某些特定配置或更复杂的情况下,可能会出现500 Internal Server Error,如原始问题中所示的HttpRequestMethodNotSupportedException。这通常意味着Spring找到了一个潜在的处理器(可能是因为路径部分匹配),但发现该处理器不支持当前的HTTP方法。
测试“空”ID的示例:
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.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.mockito.Mockito.verifyNoInteractions; @WebMvcTest(WalletController.class) class WalletControllerTest { @Autowired private MockMvc mockMvc; @MockBean private WalletService walletService; @Test void shouldReturnClientErrorWhenWalletIdIsEmptyString() throws Exception { // Given String idString = ""; // 空字符串作为ID,导致URI变为 /api/wallet/ // When mockMvc.perform(delete("/api/wallet/{id}", idString) // 生成 /api/wallet/ .contentType(MediaType.APPLICATION_JSON)) // Then // 期望4xx客户端错误,因为 /api/wallet/ 不匹配 /{id} 模式 // 具体是404 Not Found 或 405 Method Not Allowed 取决于其他映射 .andExpect(status().is4xxClientError()); // 验证服务层方法未被调用,因为请求根本没有匹配到带有ID的DELETE端点 verifyNoInteractions(walletService); } }
在这个测试中,我们期望得到一个4xx客户端错误。404 Not Found是最常见的响应,因为它表示没有找到匹配/api/wallet/且支持DELETE方法的处理器。405 Method Not Allowed也可能发生,如果/api/wallet/路径存在但只支持其他HTTP方法。
4. 注意事项与最佳实践
- 精确匹配路径: 确保你的MockMvc请求路径与控制器定义的路径注解(如@RequestMapping, @GetMapping, @DeleteMapping等)精确匹配。路径变量({})是占位符,它们需要被实际的值填充。
- 区分路径变量与请求参数: 路径变量是URI的一部分,用于标识资源。请求参数(例如/api/wallet?id=123)则通过@RequestParam注解处理。不要混淆它们的用法。
- 验证链的理解: 当路径不匹配时,请求可能根本不会到达控制器方法内部的验证逻辑(如@Min(1))。Spring的请求映射机制会在更早的阶段(路由阶段)处理URI匹配。
- 清晰的测试命名: 使用描述性强的测试方法名,清晰地表达测试的目的和预期结果(例如shouldReturnBadRequestWhenWalletIdIsZeroDueToValidation)。
- 验证服务层交互: 在测试控制器时,除了验证HTTP状态码,还应验证模拟的服务层是否被调用(或未被调用),以及调用时传入的参数是否正确。
总结
通过本文的讲解和示例,我们深入理解了在Spring MockMvc中测试DELETE请求时,如何正确处理路径变量。关键在于理解MockMvc的URL模板机制,并区分零值ID与空字符串ID在请求路径解析上的不同。对于零值ID,如果存在验证规则,预期会得到400 Bad Request;而对于空字符串ID,由于URI不匹配,通常会得到404 Not Found或405 Method Not Allowed。掌握这些细节,将有助于编写更健壮、更准确的控制器测试。
以上就是《SpringMockMvc删除接口测试教程》的详细内容,更多关于的资料请关注golang学习网公众号!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
467 收藏
-
141 收藏
-
277 收藏
-
391 收藏
-
474 收藏
-
498 收藏
-
236 收藏
-
113 收藏
-
159 收藏
-
404 收藏
-
192 收藏
-
425 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习