Springboot笔记<13>单元测试
单元测试
Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库,使用@SpringBootTest注解会以springboot的环境启动
JUnit5常用注解
@Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
@ParameterizedTest :表示方法是参数化测试
@RepeatedTest :表示方法可重复执行
@DisplayName :为测试类或者测试方法设置展示名称
@BeforeEach :表示在每个单元测试之前执行
@AfterEach :表示在每个单元测试之后执行
@BeforeAll :表示在所有单元测试之前执行
@AfterAll :表示在所有单元测试之后执行
@Tag :表示单元测试类别,类似于JUnit4中的@Categories
@Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
@Timeout :表示测试方法运行如果超过了指定时间将会返回错误
@ExtendWith :为测试类或测试方法提供扩展类引用
断言(assertions)
断言(assertions)是测试方法中的核心部分,用来对测试需要满足的条件进行验证。这些断言方法都是 org.junit.jupiter.api.Assertions 的静态方法。JUnit 5 内置的断言可以分成如下几个类别:
1、简单断言
用来对单个值进行简单的验证。如:
| assertEquals | 判断两个对象或两个原始类型是否相等 |
|---|---|
| assertNotEquals | 判断两个对象或两个原始类型是否不相等 |
| assertSame | 判断两个对象引用是否指向同一个对象 |
| assertNotSame | 判断两个对象引用是否指向不同的对象 |
| assertTrue | 判断给定的布尔值是否为 true |
| assertFalse | 判断给定的布尔值是否为 false |
| assertNull | 判断给定的对象引用是否为 null |
| assertNotNull | 判断给定的对象引用是否不为 null |
@Test
@DisplayName("simple assertion")
public void simple() {
assertEquals(3, 1 + 2, "simple math");
assertNotEquals(3, 1 + 1);
assertNotSame(new Object(), new Object());
Object obj = new Object();
assertSame(obj, obj);
assertFalse(1 > 2);
assertTrue(1 < 2);
assertNull(null);
assertNotNull(new Object());
}
2、数组断言
通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等
@Test
@DisplayName("array assertion")
public void array() {
assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
3、组合断言
assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言,可以通过 lambda 表达式很容易的提供这些断言
@Test
@DisplayName("assert all")
public void all() {
assertAll("Math",
() -> assertEquals(2, 1 + 1),
() -> assertTrue(1 > 0)
);
}
4、异常断言
在JUnit4时期,想要测试方法的异常情况时,需要用@Rule注解的ExpectedException变量还是比较麻烦的。而JUnit5提供了一种新的断言方式Assertions.assertThrows() ,配合函数式编程就可以进行使用。
@Test
@DisplayName("异常测试")
public void exceptionTest() {
ArithmeticException exception = Assertions.assertThrows(
//扔出断言异常
ArithmeticException.class, () -> System.out.println(1 % 0));
}
5、超时断言
Junit5还提供了Assertions.assertTimeout() 为测试方法设置了超时时间
@Test
@DisplayName("超时测试")
public void timeoutTest() {
//如果测试方法时间超过1s将会异常
Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}
6、快速失败
通过 fail 方法直接使得测试失败
@Test
@DisplayName("fail")
public void shouldFail() {
fail("This should fail");
}
前置条件(assumptions)
JUnit 5 中的前置条件(assumptions【假设】)类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要。Assumptions和Assertions容易混淆,因此这里通过对比它们来学习:
- Assertions即断言类,里面提供了很多静态方法,例如assertTrue,如果assertTrue的入参为false,就会抛出AssertionFailedError异常,Junit对抛出此异常的方法判定为失败;
- Assumptions即假设类,里面提供了很多静态方法,例如assumeTrue,如果assumeTrue的入参为false,就会抛出TestAbortedException异常,Junit对抛出此异常的方法判定为跳过;
- 简单的说,Assertions的方法抛出异常意味着测试不通过,Assumptions的方法抛出异常意味着测试被跳过;
@DisplayName("前置条件")
public class AssumptionsTest {
private final String environment = "DEV";
@Test
@DisplayName("simple")
public void simpleAssume() {
assumeTrue(Objects.equals(this.environment, "DEV"));
assumeFalse(() -> Objects.equals(this.environment, "PROD"));
}
@Test
@DisplayName("assume then do")
public void assumeThenDo() {
assumingThat(
Objects.equals(this.environment, "DEV"),
() -> System.out.println("In DEV")
);
}
}
1.assumeTrue可以接受Supplier类型作为第二个入参,如果assumeTrue失败就会将第二个参数的内容作为失败提示:
2.assumingThat方法,可以接受Executable类型作为第二个入参,如果第一个入参为true就会执行Executable的execute方法,注意assumingThat方法的特点:不抛出异常,因此其所在的方法不会被跳过,这是和assumeTrue相比最大的区别(assumeTrue一旦入参为false就会抛出异常,其所在方法就被标记为跳过)
嵌套测试
JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。
参数化测试
参数化测试是JUnit5很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。
利用@ValueSource等注解,指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。
@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
@NullSource: 表示为参数化测试提供一个null的入参
@EnumSource: 表示为参数化测试提供一个枚举入参
@CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
@MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
当然如果参数化测试仅仅只能做到指定普通的入参还达不到让我觉得惊艳的地步。让我真正感到他的强大之处的地方在于他可以支持外部的各类入参。如:CSV,YML,JSON 文件甚至方法的返回值也可以作为入参。只需要去实现ArgumentsProvider接口,任何外部文件都可以作为它的入参。
@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {
System.out.println(string);
Assertions.assertTrue(StringUtils.isNotBlank(string));
}
@ParameterizedTest
@MethodSource("method") //指定方法名
@DisplayName("方法来源参数")
public void testWithExplicitLocalMethodSource(String name) {
System.out.println(name);
Assertions.assertNotNull(name);
}
static Stream<String> method() {
return Stream.of("apple", "banana");
}
Springboot笔记<13>单元测试的更多相关文章
- SpringBoot学习笔记:单元测试
SpringBoot学习笔记:单元测试 单元测试 单元测试(英语:Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作.程序单元是应用的最小可测试部 ...
- 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...
- Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法
Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...
- 读书笔记-实用单元测试(英文版) Pragmatic Unit Testing in C# with NUnit
读书笔记-实用单元测试(英文版) Pragmatic Unit Testing in C# with NUnit Author: Andrew Hunt ,David Thomas with Matt ...
- SQL反模式学习笔记13 使用索引
目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引. 索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了 ...
- JAVA自学笔记13
JAVA自学笔记13 1.StringBuffer类 1)线程安全的可变字符序列 线程安全(即同步) 2)StringBuffer与String的区别:一个可变一个不可变 3)构造方法: ①publi ...
- golang学习笔记13 Golang 类型转换整理 go语言string、int、int64、float64、complex 互相转换
golang学习笔记13 Golang 类型转换整理 go语言string.int.int64.float64.complex 互相转换 #string到intint,err:=strconv.Ato ...
- springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定
springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...
- 强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods)
强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods) 学习笔记: Reinforcement Learning: An Introduction, Richa ...
- Python3+Selenium3+webdriver学习笔记13(js操作应用:弹出框无效如何处理)
#!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记13(js操作应用:弹出框无效如何处理)'''from sel ...
随机推荐
- gorm中使用乐观锁
乐观锁简介 乐观锁(又称乐观并发控制)是一种常见的数据库并发控制策略. 乐观并发控制多数用于数据竞争(data race)不大.冲突较少的环境中,这种环境中,偶尔回滚事务的成本会低于读取数据时锁定数据 ...
- goland JetBrains编辑器:代码爆红找不到引用,但项目可运行
前言 goland JetBrains 编辑器:代码爆红找不到引用,但项目可运行 解决 goland 缓存已满,需要清除缓存
- docker中 启动所有的容器命令
docker中 启动所有的容器命令 docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) docker中 关闭所有的容器命令 ...
- Python提取pdf文字信息
目录 Python提取pdf文字信息 需求 代码 总结 Python提取pdf文字信息 需求 今天教务处导出来我们全年级的成绩,一看吓一跳,我们的名字怎么不在文件名里,只能一个个找吗.事情开始变得离谱 ...
- SpringSecurity5(11-跨域配置)
SpringBoot跨域处理 @CrossOrigin(局部跨域) 作用在方法上 @RestController public class IndexController { @CrossOrigin ...
- Ink 和 TravisCI 更配哦
前言 去年还是前年,无意间接触到ink,看到是用go写的,非常小巧和精简,于是乎fork了下,还整了个供ink用的docker镜像``. 不过那时候热衷于折腾博客...结果也没折腾出什么来, 今天整理 ...
- 『Plotly实战指南』--箱线图绘制与应用
在数据可视化领域,箱线图(Box Plot)是一种强大的工具,用于展示数据的分布特征.集中趋势以及异常值. 它不仅能够快速揭示数据的偏态.离散程度,还能帮助我们识别潜在的数据问题. 本文将从基础绘制到 ...
- .NET 阻止关机机制以及关机前执行业务
本文主要介绍Windows在关闭时,如何正确.可靠的阻止系统关机以及关机前执行相应业务.因有一些场景需要在关机/重启前执行业务逻辑,确保下次开机时数据的一致性以及可靠性. 以下是实现这一需求的几种方法 ...
- 【自用】MySQL数据库基本操作
docker 中下载 mysql docker pull mysql 启动 docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12 ...
- Laravel配置Route调用artisan
//web调用artisan Route::get('/artisan', function(\Illuminate\Http\Request $request) { $all = \Illumina ...