「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」。
- JUnit 5 变化
⭐Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库
作为最新版本的 JUnit 框架,JUnit5 与之前版本的 JUnit 框架有很多的不同,由三个不同子项目的几个不同模块组成:
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit Platform: JUnit Platform 是在 JVM 上启动测试框架的基础,不仅支持 JUnit 自制的测试引擎,其他猜测是引擎也都可以接入。
JUnit Jupiter: JUnit Jupiter 提供了 JUnit 5 的鑫编程模型,是 JUnit 5 新特性的核心。内部包含了一个测试引擎,用于在 JUnit Platform 上运行。
JUnit Vintage: 由于 JUint 已经发展多年,为了照顾老的项目,JUnit Vintage 提供了兼容 JUnit4.x, Junit3.x 的测试引擎。
注意:
- Spring Boot 2.4 以上版本移除了默认对 Vintage 的依赖。如果需要兼容 junit4 需要自行引入(不能使用 junit4 的功能 @Test)
1 | xml复制代码<dependencies> |
1.1 JUnit4 & JUnit5
以前 JUnit4 的使用:
1 | java复制代码import entity.Book; |
现在 JUnit5 的使用:
1 | java复制代码import entity.Book; |
- JUnit 5 的常用注解
JUnit 5 的注解与 JUnit 4 的注解有所变化:junit.org/junit5/docs…
- @Test:表示方法是测试方法,但与 JUnit4 的 @Test 不同,它的职责非常单一,不能声明任何属性,拓展的测试将会由 Jupiter 提供额外测试
- @ParameterizedTest:表示方法是参数化测试,下文介绍
- @RepeatedTest:表示方法可重复执行,下文介绍
- @DisplayName:为测试类或者测试方法设置展示名称
- @BeforeEach:表示在每个单元测试之前执行
- @AfterEach:表示在每个单元测试之后执行
- @BeforeAll:表示在所有单元测试之前执行
- @AfterAll:表示在所有单元测试之后执行
- @Tag:表示单元测试类别,类似于 JUnit4 中的 @Categories
- @Disabled:表示测试类或测试方法不执行,类似于 JUnit4 中的 @Ignore
- @Timeout:表示测试方法运行如果超过指定时间将会返回错误
- @ExtendWith:为测试类或测试方法提供扩展类引用
2.1 @RepeatedTest
1 | java复制代码@SpringBootTest |
2.2 @DisplayName
1 | java复制代码@DisplayName("JUnit5测试类") |
2.3 @BeforeEach & @AfterEach
1 | java复制代码@DisplayName("JUnit5测试类") |
2.4 @BeforeAll & @AfterAll
1 | java复制代码@DisplayName("JUnit5测试类") |
2.5 @Disabled
1 | java复制代码@Test |
2.6 @Timeout
@Timeout
规定超时时间,超过指定时间后会抛出异常。
1 | java复制代码@Test |
- 断言机制
断言(Assertions)是测试方法中的核心部分,用来对测试需要满足的条件进行验证。这些断言方法都是 org.junit.jupiter.api.Assertions
的静态方法。
JUnit 5 内置的断言可以分成如下几个类别:
- 检查业务逻辑返回的数据是否合理
- 所有的测试运行结束以后,会有一个详细的测试报告
3.1 简单断言
用来对单个值进行简单的验证,如:
方法 | 说明 |
---|---|
assertEquals |
判断两个对象或两个原始类型是否相等 |
assertNotEquals |
判断两个对象或两个原始类型是否不相等 |
assertSame |
判断两个对象引用是否指向同一个对象 |
assertNotSame |
判断两个对象引用是否指向不同的对象 |
assertTrue |
判断给定的布尔值是否为 true |
assertFalse |
判断给定的布尔值是否为 false |
assertNull |
判断给定的对象引用是否为 null |
assertNotNull |
判断给定的对象引用是否不为 null |
3.1.1 assertEquals() & assertNotEquals()
1 | java复制代码@SpringBootTest |
3.1.2 assertSame() & assertNotSame()
1 | java复制代码@SpringBootTest |
3.1.3 assertTrue/False() & assertNull/NotNull()
1 | java复制代码@SpringBootTest |
3.2 数组断言
通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等。
1 | java复制代码@Test |
3.3 组合断言
assertAll 方法接受多个 org.junit.jupiter.api.Executable
函数式接口的实例作为要验证的断言,可以通过 lambda 表达式很容易的提供这些断言。
3.4 异常断言
在 JUnit4 时期,想要测试方法的异常情况时,需要用 @Rule 注解的 ExpectedException 变量还是比较麻烦的。而 JUnit5 提供了一种新的断言方式 Assertions.assertThrows(),配合函数式编程就可以进行使用。
1 | java复制代码@Test |
3.5 超时断言
Junit5 还提供了 Assertions.assertTimeout() 为测试方法设置了超时时间。
1 | java复制代码@Test |
3.6 快速失败
通过 fail 方法直接使得测试失败。
1 | java复制代码@Test |
- 前置条件
JUnit 5 中的前置条件类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。
1 | java复制代码@SpringBootTest |
并没有打印 “后续..” 语句且无报错:
- 嵌套测试
JUnit 5 可以通过 Java 中的内部类和 @Nested
注解实现嵌套测试,从而可以更好地将相关的测试方法组织在一起。在内部类中可以使用 @BeforeEach
和 @AfterEach
注解,而且嵌套的层次没有限制。
1 | java复制代码@SpringBootTest |
- 参数化测试
参数化测试是 JUnit5 很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。
利用 @ValueSource 等注解指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。
- @ValueSource:为参数化测试指定入参来源,支持八大基础类以及 String 类型,Class 类型
- @NullSource:表示为参数化测试提供一个 null 的入参
- @EnumSource:表示为参数化测试提供一个枚举入参
- @CsvFileSource:表示读取指定 CSV 文件内容作为参数化测试入参
- @MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
当然如果参数化测试仅仅只能做到指定普通的入参还达不到令人惊艳的地步。
⭐它真正的强大之处的地方在于可以支持外部的各类入参。如:CSV,YML,JSON 文件甚至方法的返回值也可以作为入参。只需要去实现 ArgumentsProvider 接口,任何外部文件都可以作为它的入参。
6.1 @ValueSource & @ParameterizedTest
1 | java复制代码@SpringBootTest |
6.2 @MethodSource & @ParameterizeTest
1 | java复制代码@SpringBootTest |
- JUnit 迁移指南
在进行迁移的时候需要注意如下的变化:
- 注解在
org.junit.jupiter.api
包中,断言在org.junit.jupiter.api.Assertions
类中,前置条件在org.junit.jupiter.api.Assumptions
类中 - 把
@Before
和@After
替换成@BeforeEach
和@AfterEach
- 把
@BeforeClass
和@AfterClass
替换成@BeforeAll
和@AfterAll
- 把
@Ignore
替换成@Disabled
- 把
@Category
替换成@Tag
- 把
@RunWith
、@Rule
和@ClassRule
替换成@ExtendWith
希望本文对你有所帮助🧠
欢迎在评论区留下你的看法🌊,我们一起讨论与分享🔥
本文转载自: 掘金