# JUnit5

Spring Boot 2.2.0 开始引入 JUnit5 作为默认单元测试库。

# 参考文档

# 组成

Junit5 由三部分组成:

  • JUnit Platform
  • JUnit Jupiter
  • JUnit Vintage

# JUnit Platform

JUnit Platform 是在 JVM 上启动测试框架的基础,不仅支持 JUnit 自制的测试引擎,其他测试引擎也都可以接入。

# Junit Jupiter

JUnit Jupiter 提供了 JUnit5 新的编程模型,是 JUnit5 新特性的核心。内部包含了一个测试引擎,用于在 JUnit Platform 上运行。

# Junit Vintage

由于 JUnit 项目已经开发了很多年,为了照顾老的项目,JUnit Vintage 提供了兼容 JUnit4.x、JUnit3.x 的测试引擎。

Spring Boot 2.4 之后移除了默认对 Vintage 的依赖。如果需要使用 JUnit4 则需要自行引入依赖:

<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>
1
2
3
4
5
6
7
8
9
10
11

# 注解 Annotations

  • @Test:表示方法是测试方法,但是与 Junit4 的 @Test 不同,它的职责非常单一,不能声明任何属性,拓展的测试将会由 Jupiter 提供额外测试。
  • @DisplayName:为测试类或测试方法设置展示名称。
  • @ParameterizedTest:表示方法是参数化测试。
  • @RepeatedTest:表示方法可重复执行。
  • @BeforeEach:表示在每个单元测试之前执行。
  • @AfterEach:表示在每个单元测试之后执行。
  • @BeforeAll:表示在所有单元测试之前执行。
    • 要加 static 关键字修饰,因为只会在整个测试类之前运行一次。
  • @AfterAll:表示在所有单元测试之后执行。
    • 要加 static 修饰,理由同上。
  • @Disabled:表示测试类或测试方法不执行。
    • 一个测试类中多个测试实例,该注解可以选择禁用某个实例。
  • @TimeOut:表示测试方法运行如果超过了指定时间,将会返回错误。
  • @ExtendWith:为测试类或测试方法提供扩展类引用。
    • 之前版本使用 @RunWith
  • @Tag:表示单元测试类别,类似于 JUnit4 中的 @Categories

# Assertions 断言

示例:Assertions.assertEquals(expected, actual, message)

一个 test 中有两处断言,前面的断言失败后,程序不会继续执行。

# 简单断言

  • assertEquals,判断两个对象或原始类型是否相等
  • assertNotEquals
  • assertSame,判断两个对象的引用是否指向同一个对象
  • assertNotSame
  • assertNull,判断给定的对象引用是否为 Null
  • assertNotNull
  • assertTrue,判断给定的值是否为 true
  • assertFalse

# 数组断言

  • assertArrayEquals,判断两个对象或原始类型的数组是否相等。

这里判断的是数组的内容,而不是数组的地址。

# 组合断言

判定多个断言是否都成功。

示例:

assertAll("test",
    () -> assertTrue(1 == 1, "返回的不是 true"),
    () -> assertEquals(2, 1, "得到的值不是 2"));
1
2
3

这里只有两个断言都成功的时候,才会成功,有一个断言不成功,那么 assertAll 就执行失败。

# 异常断言

示例:

assertThrows(
    NullPointerException.class,
    () -> { int q = 9 / 0; },
    "竟然正常运行了"
    );
1
2
3
4
5

期望的逻辑执行时会发生 NPE,但是却没有发生这个异常就,那么就显示自定义的 Message。

# 超时断言

示例:

assertTimeout(Duration.ofMillis(1), () -> {
    Thread.sleep(2);
}, "程序超时了");
1
2
3

期望程序在 1 毫秒执行完毕,但是这里却大于 1 毫秒,所有这里断言失败了,打印信息 "程序超时了"。

# 快速失败

fail("测试失败");

# Assumptions 假设

也可以理解为前置条件。

Assumptions.assumeTrue("56".equals("ss"),"假设不成立,程序不继续执行");

假设成立,代码会向下执行,不成立的时候,程序会终止,直接跳过 test。

断言不满足会报失败,而假设则是不继续执行。

# 嵌套测试

在嵌套测试时内层的测试会触发外层的 BeforeEach ... 方法,但是外层的方法不会驱动内层的方法。

# Parameterized Tests 参数化测试

生成参数注解:

  • @ValueSource
  • @NullSource
  • @EnumSource
  • @CsvFileSource
  • @MethodSource
    • 这种方式需要导入的方法需要是 static 的,并且返回值是 Stream 的。

示例:

@DisplayName("Parameterized Tests")
@ParameterizedTest
@ValueSource(ints = {1,2,3})
void ParameterizedTest(int i) {
    System.out.println(i);
}
1
2
3
4
5
6

# 讨论区

由于评论过多会影响页面最下方的导航,故将评论区做默认折叠处理。

点击查看评论区内容,渴望您的宝贵建议~
Last Updated: 2/17/2023, 11:30:03 AM