当前位置: 首页 > news >正文

Spring Boot Controller 单元测试撰写

文章目录

      • 引言
      • 标准用法
        • 必需依赖项
        • 核心注解说明
        • 代码示例
      • 当涉及静态方法时的测试策略
        • 必需依赖项
        • 核心注解说明
        • 代码示例

引言

之前在编写 Controller 层的单元测试时,我一直使用 @SpringBootTest 注解,但它会加载整个 Spring 应用上下文,资源开销大,我更倾向于采用更轻量级的测试策略,专注于 Web 层的功能验证。

在最近的单元测试撰写中,我采用了新的方法,并在此归纳记录:

标准用法

必需依赖项

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><!-- 版本可根据项目实际情况调整,需要和spring-boot版本适应--><scope>test</scope>
</dependency>
<!-- 如果不报错,一般不需要引入 -->
<dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-launcher</artifactId><version>1.8.2</version><scope>test</scope>
</dependency>
<!-- 仅在需兼容 JUnit 4/3 时使用 -->
<dependency><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId><version>5.8.2</version><scope>test</scope>
</dependency>
核心注解说明
  • @WebMvcTest(controllers = YourController.class)

Spring Boot 提供的切片测试注解,专门用于测试 MVC 控制器层。它只加载 Spring MVC 相关组件(如 @Controller、@RestController、@ControllerAdvice 等),不会加载 Service、Repository 等其他 Bean。

  • @ContextConfiguration(classes = YourController.class)

明确指定测试所需加载的配置类或组件,避免因自动注入无关 Bean 而导致测试失败。

代码示例
@WebMvcTest(controllers = YourController.class)
@ContextConfiguration(classes = YourController.class)
class YourControllerTest {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate YourService yourService;@Autowiredprivate ObjectMapper objectMapper;@Testvoid getSomething() throws Exception {// 模拟service层方法调用when(yourService.getSomething(anyString())).thenReturn(R.ok());// 模拟请求参数HashMap<String, Object> requestBody = new HashMap<>();requestBody.put("testParam", "test");// 开始模拟mockMvc.perform(MockMvcRequestBuilders.post("/xx/getSomething").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(requestBody))).andDo(MockMvcResultHandlers.print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$.code").value(R.ok().getCode())).andExpect(jsonPath("$.data").isEmpty());}
}

当涉及静态方法时的测试策略

在极端情况下,如果 Controller 中存在通过工厂类静态方法构造的依赖(而不是通过 Spring 注入),该如何进行测试?

必需依赖项

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><!-- 版本自选,需要和spring-boot版本适应--><exclusions><exclusion><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId></exclusion></exclusions><scope>test</scope>
</dependency><!--不报错就没必要加它-->
<dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-launcher</artifactId><version>1.8.2</version><scope>test</scope>
</dependency>
<dependency><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId><version>5.8.2</version><scope>test</scope>
</dependency>
<!--旧版本 mockito-core 不支持静态方法 mock-->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>5.2.0</version><scope>test</scope>
</dependency>
核心注解说明
  • @ExtendWith(MockitoExtension.class)

启用 Mockito 的注解功能,包括 @Mock、@InjectMocks、@Spy 等支持。

代码示例
@ExtendWith(MockitoExtension.class)
class YourControllerTest {private ObjectMapper objectMapper = new ObjectMapper();@Testvoid getSomething() throws Exception {try(MockedStatic<XxxFactory> mocked = mockStatic(XxxFactory.class)){//用来替换的对象YourInstance instance = mock(YourInstance.class);//静态替换mocked.when(XxxFactory::getYourInstance).thenReturn(instance);//模拟方法调用when(instance.getSomething(anyString())).thenReturn(R.ok());// 模拟请求参数HashMap<String, Object> requestBody = new HashMap<>();requestBody.put("testParam", "test");// 开始模拟mockMvc.perform(MockMvcRequestBuilders.post("/xx/getSomething").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(requestBody))).andDo(MockMvcResultHandlers.print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(jsonPath("$.code").value(R.ok().getCode())).andExpect(jsonPath("$.data").isEmpty());}}}

相关文章:

  • Git删除指定历史版本
  • 快速配置linux远程开发-go语言
  • Docker部署DeepSeek常见问题及解决方案
  • 实战交易策略 篇十九:君山居士熊市交易策略
  • 机器学习 Day14 XGboost(极端梯度提升树)算法
  • 得物业务参数配置中心架构综述
  • 大语言模型之提示词技巧
  • Tomcat:从零理解Java Web应用的“心脏”
  • 路由交换网络专题 | 第七章 | BGP练习 | 次优路径 | Route-Policy | BGP认证
  • Typecho 访客统计插件最新版-前后台统计图均可显示
  • 搭建私人网站
  • 香港国际视角下的资金路径识别与结构研判
  • 数理逻辑基础 | 命题逻辑 / 谓词逻辑 / 命题符号化
  • nodejs之Express-介绍、路由
  • Godot开发2D冒险游戏——第二节:主角光环整起来!
  • JDK 21 的新特性:探索 Java 的最新进化
  • ubantu中下载编译安装qt5.15.3
  • (51单片机)LCD展示动画(延时函数)(LLCD1602教程)
  • JVM(Java虚拟机)详解
  • JVM-类加载机制
  • 王沪宁会见越共中央委员、越南祖国阵线中央副主席兼秘书长阮氏秋荷
  • 印控克什米尔恐袭引爆印巴新一轮外交摩擦,地区安全风险骤增
  • 何立峰出席跨境贸易便利化专项行动部署会并讲话
  • 汪东进卸任中海油董事长,深耕油气领域40余年、已临近退休
  • 海南陵水一酒店保洁员调包住客港币,被判刑一年六个月
  • 研究显示:日行9000步最高可将癌症风险降低26%