当前位置:首页 > 文章列表 > 文章 > java教程 > SpringMockMvc删除接口测试教程

SpringMockMvc删除接口测试教程

2025-07-24 10:03:34 0浏览 收藏

在文章实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Spring MockMvc 删除请求测试教程》,聊聊,希望可以帮助到正在努力赚钱的你。

Spring MockMvc DELETE请求路径变量测试指南

本文深入探讨了如何使用Spring MockMvc正确测试RESTful DELETE请求,特别是涉及路径变量(如ID)的场景。文章详细解释了MockMvc URL模板的正确用法,区分了空ID与零值ID在路径变量中的处理方式,并分析了当请求路径与控制器定义不匹配时可能出现的HTTP状态码及其深层原因,旨在帮助开发者避免常见的测试陷阱,确保测试的准确性和健壮性。

在开发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 ResponseEntity<WalletDTO> deleteWalletById(@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学习网公众号!

电脑蓝屏0x0000001A解决方法大全电脑蓝屏0x0000001A解决方法大全
上一篇
电脑蓝屏0x0000001A解决方法大全
PhpStorm代码格式化设置与快捷键使用指南
下一篇
PhpStorm代码格式化设置与快捷键使用指南
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    512次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    499次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 千音漫语:智能声音创作助手,AI配音、音视频翻译一站搞定!
    千音漫语
    千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
    869次使用
  • MiniWork:智能高效AI工具平台,一站式工作学习效率解决方案
    MiniWork
    MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
    824次使用
  • NoCode (nocode.cn):零代码构建应用、网站、管理系统,降低开发门槛
    NoCode
    NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
    857次使用
  • 达医智影:阿里巴巴达摩院医疗AI影像早筛平台,CT一扫多筛癌症急慢病
    达医智影
    达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
    875次使用
  • 智慧芽Eureka:更懂技术创新的AI Agent平台,助力研发效率飞跃
    智慧芽Eureka
    智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
    849次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码