Spring boot如何执行单元测试?

news/2024/5/22 4:40:35/文章来源:https://blog.csdn.net/Sgxlebron/article/details/137336197

Spring Boot 提供了丰富的测试功能,主要由以下两个模块组成:

  • spring-boot-test:提供测试核心功能。
  • spring-boot-test-autoconfigure:提供对测试的自动配置。

Spring Boot 提供了一个 spring-boot-starter-test一站式启动器,如以下依赖配置所示。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

测试启动器依赖不仅包含以上两个 Spring Boot模块,还包含 Spring Test 测试模块,以及其他

第三方测试类库,如下所示。

  • JUnit 5:Java 最主流的单元测试框架。
  • AssertJ:一款快速断言库。
  • Hamcrest:一款单元测试匹配库。
  • Mockito:一款 Mock 测试框架。
  • JSONassert:一款 JSON 断言库。
  • JsonPath:一款 JSON XPath 库。

更多测试相关的依赖可见具体的依赖关系树,如下图所示。
在这里插入图片描述

以上这些都是 Spring Boot 提供的常用的测试类库,如果上面的测试类库还不能满足你的需要,也可以任意添加以上没有的类库。

现在基本上使用的是 JUnit 5,如果应用还在使用JUnit 4 写的单元测试用例,那么也可以使用JUnit 5 的 Vintage 引擎来运行,如下面的依赖配置所示。

<dependency><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.hamcrest</groupId><artifactId>hamcrest-core</artifactId></exclusion></exclusions>
</dependency>

需要排除 hamcrest-core 依赖,因为该依赖已经改坐标了,并且默认内置在Spring Boot依赖管理中,如上面的依赖关系树所示,最新的 Hamcrest依赖已经是org.hamcrest:hamcrest坐标了。

Spring Boot提供了一个 @SpringBootTest 注解,用在单元测试类上以启用支持Spring Boot特性的单元测试,如果使用的是JUnit 4,那么测试类上还需要额外的@RunWith(SpringRunner. class)注解,然后在测试类方法上添加 @Test 注解即可,每一个 @Test 注解修饰的方法就是一个单元测试方法。

@SpringBootTest 注解有一个最重要的 webEnvironment 环境参数,支持以下几种环境设置:

  • MOCK(默认): 加载一个 Web ApplicationContext 并提供一个 Mock Web Environment,但不会启动内嵌的 Web 服务器,并可以结合 @AutoConfifigureMockMvcor@AutoConfifigure-WebTestClient 注解一起使用进行 Mock 测试。
  • RANDOM_PORT: 加载一个 WebServerApplicationContext,以及提供一个真实的 WebEnvironment,并以随机端口启动内嵌服务器。
  • DEFINED_PORT: 和 RANDOM_PORT 一样,不同的是 DEFINED_PORT 是以应用指定的端口运行的,默认端口为 8080。
  • NONE: 加载一个 ApplicationContext,但不会提供任何 Web Environment
    如果使用的 @SpringBootTest 注解不带任何参数,则默认为 Mock 环境。

真实环境测试

@SpringBootTest 注解中指定基于随机端口的真实Web环境,然后在类成员变量或者方法参数上注入 TestRestTemplate 实例,就可以完成对 Spring MVC接口的真实环境测试。

下面是一个基于随机端口的真实环境的测试用例:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MvcTest {@Testpublic void getUserTest(@Autowired TestRestTemplate testRestTemplate) {Map<String, String> multiValueMap = new HashMap<>();multiValueMap.put("username", "Java 技术栈 ");Result result = testRestTemplate.getForObject("/user/get?username={username}",Result.class, multiValueMap);assertThat(result.getCode()).isEqualTo(0);assertThat(result.getMsg()).isEqualTo("ok");}}

测试当前应用下的 /user/get 接口,传入对应的用户名参数,最后检查接口返回结果是否和预期一致,测试结果如下图所示。

在这里插入图片描述

单元测试通过,从执行日志可以看到,它启动了一个嵌入式的 Tomcat 容器来测试真实的 Web应用环境。

Mock 环境测试

通过在类上面使用 @AutoConfifigureMockMvc 注解,然后在类成员变量或者方法参数上注入MockMvc 实例,就可以完成对 Spring MVC 接口的 Mock 测试。

下面是一个基于默认 Mock 环境的测试用例:

@SpringBootTest
@AutoConfigureMockMvc
class MockMvcTests {@Testpublic void getUserTest(@Autowired MockMvc mvc) throws Exception {mvc.perform(MockMvcRequestBuilders.get("/user/get?username={username}", "test")).andExpect(status().isOk()).andExpect(content().string("{\"code\":0,\"msg\":\"ok\",\"
data\":\"test\"}"));}
}

测试当前应用下的 /user/get 接口,传入对应的用户名参数,最后检查请求状态是否OK(200),响应的内容是否和预期一致,测试结果如下图所示。
在这里插入图片描述

单元测试通过,从执行日志可以看到,它并未启动真实的 Web 环境来测试,而是使用 Mock 环境测试的。

Mock 组件测试

某些时候可能还需要模拟一些组件,比如某些服务只有上线之后才能调用,在开发阶段不可用,这时就需要 Mock 模拟测试了,提供各种模拟组件以完成测试。

Spring Boot 提供了一个 @MockBean 注解,可为 Spring 中的 Bean 组件定义基于 Mockito 的Mock 测试,它可以创建一个新 Bean 以覆盖 Spring 环境中已有的 Bean,它可以用在测试类、成员变量上,或者 @Confifiguration 配置类、成员变量上,被模拟的 Bean 在每次测试结束后自动重置。

假现现在有一个远程的服务 userService,本地不能调用,现在进行 Mock 测试,如以下使用示例所示。

@SpringBootTest
class MockBeanTests {
// @Autowired
// private UserService userService;@MockBeanprivate UserService userService;@Testpublic void countAllUsers() {BDDMockito.given(this.userService.countAllUsers()).willReturn(88);assertThat(this.userService.countAllUsers()).isEqualTo(88);}
}

这里的 @MockBean 注解使用在 UserService 变量上,表明这个userService实例在当前测试用例中是被 Mock 覆盖的,如果要模拟的 Bean 有多个,则可以使用@Qualififier注解指定,然后通过Mockito 提供的代理工具类方法创建模拟返回数据,运行该服务的测试方法,当模拟数据和预期结果一致时才会测试通过。

这里通过 BDDMockito 工具类模拟 userService#countAllUsers方法并让它返回统计的用户总数(88),最后检查该方法的返回值是否和预期一致,测试结果如下图所示。

在这里插入图片描述

单元测试通过,也可以使用 @SpyBean 注解代替 @MockBean 注解,两者的区别是:

  • @SpyBean—如果没有提供 Mockito 代理方法,则会调用真实的 Bean 来获取数据。
  • @MockBean—不管有没有提供 Mockito 代理方法,都会调用 Mock 的 Bean 来获取数据。
    @MockBean@SpyBean 注解既可作用于 Mock 环境,也可作用于真实环境,它只是用来模拟、替换环境中指定的 Bean 而已,但不能用于模拟在应用上下文刷新期间 Bean 的行为,因为在执行测试用例时应用上下文已经刷新完成了,所以不可能再去模拟了,这种情况下建议使用 @Bean 方法来创建模拟配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1045554.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unipush+个推实现消息推送

1.注册个推平台的帐号个推&#xff0c;专业的数据智能服务商-为垂直领域提供数据智能解决方案 2.应用列表中选择新增应用/服务 3.填写下应用信息4.创建好应用后在manifest.json中的sdkConfigs配置上写入appid、appkey、appsecret "sdkConfigs" : {"ad" :…

硬件学习件Cadence day16 做个笔记,BOM 位号这个参数输出的两种情况。

1. BOM 中位号有3种情况 1. 一种是位号生成时多行&#xff0c;每行是固定的位数。&#xff08;如下图所示&#xff09; 2. 一种是位号生成时只有一行&#xff0c;但是可以使用表格中自动换行功能&#xff0c;给他换行&#xff0c;但是这个位号本质上只有一行&#xff0c;只是因…

基于深度学习的乳腺癌智能检测分割与诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

虚拟网络设备的真正使命:实现有控制的通信

在数字化时代&#x1f4f2;&#xff0c;网络安全&#x1f512;成为了企业和个人防御体系中不可或缺的一部分。随着网络攻击的日益复杂和频繁&#x1f525;&#xff0c;传统的物理网络安全措施已经无法满足快速发展的需求。虚拟网络设备&#x1f5a7;&#xff0c;作为网络架构中…

一起学习python——基础篇(5)

今天讲一下python的数据类型。 数据类型主要分为文本类型、数值类型、序列类型、映射类型、集合类型、布尔类型、二进制类型六大类型。 文本类型&#xff1a;str 数值类型&#xff1a; int, float, complex 序列类型&#xff1a; list, tuple, range 映射类型&#xff1a;…

【数据结构与算法】搜索算法(深度优先搜索 DFS和广度优先搜索 BFS)以及典型算法例题

目录 搜索算法&#xff08;深度优先搜索DFS和广度优先搜索BFS&#xff09;以及典型算法例题深度优先搜索 &#xff08;Depth First Search 简称 DFS&#xff09;DFS 的设计步骤深度优先搜索&#xff08;DFS&#xff09;算法例题例题一&#xff1a;N皇后问题例题二&#xff1a;路…

SQL注入sqli_labs靶场第五、六题

第五题 根据报错信息&#xff0c;判断为单引号注入 没有发现回显点 方法&#xff1a;布尔盲注&#xff08;太耗时&#xff0c;不推荐使用&#xff09; 1&#xff09;猜解数据库名字&#xff1a;&#xff08;所有ASCII码值范围&#xff1a;0~127&#xff09; ?id1 and length…

成功解决> 错误: 无效的源发行版:17

运行项目的时候出现下面的报错&#xff1a; Execution failed for task ‘:device_info_plus:compileDebugJavaWithJavac’. 错误: 无效的源发行版&#xff1a;17 原因&#xff1a;没有设置好自己项目的JDK版本 解决&#xff1a;1.检查自己项目的JDK版本 将自己的项目改为JDK 1…

MySQL高级(索引分类-聚集索引-二级索引)

目录 1、主键索引、唯一索引、常规索引、全文索引 2、 聚集索引、二级索引 3、回表查询 4、通过id查询和通过name查询那个执行效率高&#xff1f; 5、 InnoDB主键索引的 B tree 高度为多高呢&#xff1f; 1、主键索引、唯一索引、常规索引、全文索引 在MySQL数据库&#xff0c…

C++的stack和queue类(一):适配器模式、双端队列与优先级队列

目录 基本概念 stack的使用 queue的使用 适配器模式 stack.h test.cpp 双端队列-deque 仿函数 优先队列 priority_queue的使用 queue.h文件 stack.h文件 test.cpp文件 日期类的比较 商品的比较 结论 基本概念 1、stack和queue不是容器而是容器适配器&…

性能优化原则

相关链接&#xff1a;【运行环境】加载资源的形式 性能优化 1 性能优化原则 多使用内存、缓存或其他方法 减少CPU计算量&#xff0c;减少网络加载耗时 &#xff08;适用于所有编程的性能优化----空间换时间&#xff09; 2 从何入手 性能优化-让加载更快 减少资源体积&#x…

每日一题 — 最大连续 1 的个数III

解法一&#xff1a;暴力枚举 先定义left和right双指针&#xff0c;left先固定在起始位置&#xff0c;遍历right当值等于1的时候&#xff0c;直接跳过&#xff0c;等于0的时候&#xff0c;zero计数器加一当zero等于k的时候&#xff0c;就开始记录此时最大长度是多少然后left加一…

深度剖析:网络安全中的红蓝对抗策略

红蓝对抗 红蓝对抗服务方案 在蓝队服务中&#xff0c;作为攻击方将开展对目标资产的模拟入侵&#xff0c;寻找攻击路径&#xff0c;发现安全漏洞和隐患。除获取目标系统的关键信息&#xff08;包括但不限于资产信息、重要业务数据、代码或管理员账号等&#xff09;外&#x…

Python | 超前滞后分析

Nino SST Indices (Nino 12, 3, 3.4, 4; ONI and TNI) 有几个指标用于监测热带太平洋&#xff0c;所有这些指标都是基于海表温度(SST)异常在一个给定的区域的平均值。通常&#xff0c;异常是相对于30年的周期来计算的。厄尔尼诺3.4指数(Nio 3.4 index)和海洋厄尔尼诺指数(Ocea…

Chrome谷歌下载入口

​hello&#xff0c;我是小索奇 发现好多人说谷歌浏览器在哪里下载呀&#xff0c;哪里可以找到&#xff1f; 你可能会心想&#xff0c;一个浏览器你还不会下载啊&#xff1f; 还真是&#xff0c;有很多伙伴找不到下载入口&#xff0c;为什么呢&#xff1f; Bing进行搜索&am…

java程序 .exe启动nginx防止重复启动,已解决

java代码生成好的.exe启动nginx服务程序 根据nginx占用端口来解决nginx服务重复启动问题&#xff08;下面代码了解代码逻辑后根据自己的业务需求修改即可&#xff09; 代码&#xff1a; package org.example;import javax.swing.*; import java.awt.*; import java.io.*; …

C#/WPF 使用开源Wav2Lip做自己的数字人(无需安装环境)

实现效果 Speaker Wav2Lip概述 2020年&#xff0c;来自印度海德拉巴大学和英国巴斯大学的团队&#xff0c;在ACM MM2020发表了的一篇论文《A Lip Sync Expert Is All You Need for Speech to Lip Generation In The Wild 》&#xff0c;在文章中&#xff0c;他们提出一个叫做Wa…

ChatGPT 4.0报错 :“Hmm…something seems to have gone wrong.”

ChatGPT报错&#xff0c;GPT-3.5模型正常&#xff0c;GPT-4.0报错&#xff1a;“Hmm…something seems to have gone wrong.” 说明&#xff1a;嗯…好像出了什么问题。 原因&#xff1a; 部分用户在使用GPT-3.5模型时提问正常&#xff0c;GPT-4.0模型提问时&#xff0c;出现这…

Open CASCADE学习|求曲面的参数空间

在三维空间中&#xff0c;任意的曲面都可以通过特定的方法映射到一个二维参数平面上&#xff0c;从而对其进行详细的几何分析和处理。首先&#xff0c;我们需要从三维模型中提取出特定的曲面&#xff0c;这通常被称为“Face”。一个face可以被视为三维空间中的一个封闭区域&…

xss.pwnfunction-Ah That‘s Hawt

<svg/onloadalert%26%2340%3B1%26%2341%3B> <svg/>是一个自闭合形式 &#xff0c;当页面或元素加载完成时&#xff0c;onload 事件会被触发&#xff0c;从而可以执行相应的 JavaScript 函数