【JUnit实战3_02】第二章:探索 JUnit 的核心功能(一)

《JUnit in Action》全新第3版封面截图

写在前面

由于《JUnit in Action》这本大部头实战资料的目标受众是对 JUnit 的零基础人士,所以在介绍完第一章的开胃菜后,第二章就可以开始扫盲了。本章针对 JUnit 5 的核心特性做了一个相对全面的拉网式概述,让大家直观感受一下这个单测框架目前所具备的能力。由于知识点较多,拟根据篇幅拆分为多个小节进行梳理,本节为第二章内容的第一篇。

文章目录

  • [第二章 探索 JUnit 的核心功能](#第二章 探索 JUnit 的核心功能)
    • [2.1 相关资源](#2.1 相关资源)
    • [2.2 测试类与测试方法](#2.2 测试类与测试方法)
    • [2.3 本章示例代码的运行方法](#2.3 本章示例代码的运行方法)
    • [2.4 关于 @TestInstance 注解](#2.4 关于 @TestInstance 注解)
    • [2.5 @DisplayName 注解](#2.5 @DisplayName 注解)

第二章 探索 JUnit 的核心功能

本章概要

  • JUnit 生命周期
  • JUnit 的核心类、核心方法、核心注解
  • JUnit 运行机制演示

2.1 相关资源

2.2 测试类与测试方法

一个测试类(test class)可以是顶级类、静态成员类,或是使用 @Nested 注解的内部类,其中包含一个或多个测试方法。

测试类不能是抽象的,且必须提供单一的无参构造方法(如果确实需要参数,也可以通过运行时依赖注入的方式引入)。

测试类的在 JUnit 5 中的可见性可最低降至 包路级私有(package-private ,即不加任何访问修饰符,保持默认的 package 包级可见即可 [1](#1);此前 JUnit 4 必须声明为 public

测试方法也不能是抽象方法,并且不能有返回值(统一返回 void)。

按照加注注解的不同,可分为两大类:(普通)测试方法(test method)和生命周期方法(life cycle method),其中------

测试方法 是加注了如下注解的实例方法:

  • @Test
  • @RepeatedTest
  • @ParameterizedTest
  • @TestFactory
  • @TestTemplate

生命周期方法 是加注了如下注解的方法:

  • @BeforeAll
  • @AfterAll
  • @BeforeEach
  • @AfterEach

2.3 本章示例代码的运行方法

首先添加 Maven 依赖:

xml 复制代码
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
</dependency>

然后在命令行执行命令:

bash 复制代码
mvn test -Dtest=SpecificTestClassName

本地实测时由于手动安装并配置了 Java11,后续通过 IDEA 又安装了 Java21Java24 等多个版本,导致上述命令报错,提示编译的版本不一致:

bash 复制代码
> mvn test
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------< com.manning.junitbook:ch02-core >-------------------
[INFO] Building ch02-core 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ ch02-core ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\workspaces\juia3\ch02-core\src\main\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ ch02-core ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 19 source files to E:\workspaces\juia3\ch02-core\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.478 s
[INFO] Finished at: 2025-10-09T16:48:42+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project ch02-core: Fatal error compiling: 错误: 无效的目标发行版:1.11 -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
> 

解决方法:新增 Maven 插件手动指定编译版本为 Java11,与本机系统保持一致:

xml 复制代码
<build>
    <plugins>
        <!-- snip -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>11</source>
                <target>11</target>
            </configuration>
        </plugin>
    </plugins>
</build>

2.4 关于 @TestInstance 注解

一般情况下,JUnit 在调用每个 @Test 注解过的方法前会创建一个该测试类的新实例,以确保测试方法的独立性。

如果想让 @BeforeAll 注解的方法实现 只运行一次、然后再运行其余 @Test 用例 ,通常需要声明为 static 静态方法;否则,就必须在测试类上加注 @TestInstance 注解,并传入参数 TestInstance.Lifecycle.PER_CLASS

java 复制代码
// 1. use static
class SUTTest {
    // -- snip --
    @BeforeAll
    static void setUpClass() {
        resourceForAllTests = new ResourceForAllTests("Our resource for all tests");
    }
    // -- snip --
}

// 2. use @TestInstance annotation
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SUTTest {
    // -- snip --
    @BeforeAll
    void setUpClass() {
        resourceForAllTests = new ResourceForAllTests("Our resource for all tests");
    }
    // -- snip --
}

2.5 @DisplayName 注解

该注解方便 IDEAIDE 工具增强测试用例运行结果的可读性:

该注解的参数值支持文本、特殊字符、甚至是 emoji 表情符号,非常强大。

根据 IntelliJ IDEA 官方发布的 教学视频,可以创建自定义模板快速输入带 @DisplayName 注解的代码块:

另外,编辑变量可实现 TEST_NAMEMETHOD_NAME 的联动:

实测备忘录

在测试类上加 @Disabled 注解后,直接运行该测试类,里面的方法仍然会执行。

要让 IDEA 不执行该测试类,只能 从对应的包上 运行单元测试:

bash 复制代码
> mvn test -Dtest="com/manning/junitbook/ch02/disabled/*"

  1. JUnit 5 团队认为,测试代码是实现细节的一部分,通常不需要被外部代码所调用。将测试类的可见性降至包私有,更符合封装的原则,使得代码更加简洁。 ↩︎
相关推荐
TDengine (老段)17 小时前
TDengine 数学函数 DEGRESS 用户手册
大数据·数据库·sql·物联网·时序数据库·iot·tdengine
TDengine (老段)17 小时前
TDengine 数学函数 GREATEST 用户手册
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
安当加密18 小时前
云原生时代的数据库字段加密:在微服务与 Kubernetes 中实现合规与敏捷的统一
数据库·微服务·云原生
爱喝白开水a18 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱
想ai抽18 小时前
深入starrocks-多列联合统计一致性探查与策略(YY一下)
java·数据库·数据仓库
武子康18 小时前
Java-152 深入浅出 MongoDB 索引详解 从 MongoDB B-树 到 MySQL B+树 索引机制、数据结构与应用场景的全面对比分析
java·开发语言·数据库·sql·mongodb·性能优化·nosql
longgyy19 小时前
5 分钟用火山引擎 DeepSeek 调用大模型生成小红书文案
java·数据库·火山引擎
ytttr87319 小时前
C# 仿QQ聊天功能实现 (SQL Server数据库)
数据库·oracle·c#
盒马coding20 小时前
第18节-索引-Partial-Indexes
数据库·postgresql
不剪发的Tony老师20 小时前
CloudDM:一站式数据库开发管理工具
数据库