【JUnit实战3_02】第二章:探索 JUnit 的核心功能(一)
写在前面
由于《JUnit in Action》这本大部头实战资料的目标受众是对 JUnit 的零基础人士,所以在介绍完第一章的开胃菜后,第二章就可以开始扫盲了。本章针对 JUnit 5 的核心特性做了一个相对全面的拉网式概述,让大家直观感受一下这个单测框架目前所具备的能力。由于知识点较多,拟根据篇幅拆分为多个小节进行梳理,本节为第二章内容的第一篇。
文章目录
- 第二章 探索 JUnit 的核心功能
- 2.1 相关资源
- 2.2 测试类与测试方法
- 2.3 本章示例代码的运行方法
- 2.4 关于 @TestInstance 注解
- 2.5 @DisplayName 注解
第二章 探索 JUnit 的核心功能
本章概要
JUnit
生命周期JUnit
的核心类、核心方法、核心注解JUnit
运行机制演示
2.1 相关资源
JUnit 5
用户手册:https://docs.junit.org/current/user-guide/JUnit 5
接口文档:https://docs.junit.org/current/api/- 随书源码仓库:https://github.com/ctudose/junit-in-action-third-edition
2.2 测试类与测试方法
一个测试类(test class)可以是顶级类、静态成员类,或是使用 @Nested
注解的内部类,其中包含一个或多个测试方法。
测试类不能是抽象的,且必须提供单一的无参构造方法(如果确实需要参数,也可以通过运行时依赖注入的方式引入)。
测试类的在 JUnit 5
中的可见性可最低降至 包路级私有(package-private),即不加任何访问修饰符,保持默认的 package
包级可见即可 1;此前 JUnit 4
必须声明为 public
。
测试方法也不能是抽象方法,并且不能有返回值(统一返回 void
)。
按照加注注解的不同,可分为两大类:(普通)测试方法(test method)和生命周期方法(life cycle method),其中——
测试方法 是加注了如下注解的实例方法:
@Test
@RepeatedTest
@ParameterizedTest
@TestFactory
@TestTemplate
生命周期方法 是加注了如下注解的方法:
@BeforeAll
@AfterAll
@BeforeEach
@AfterEach
2.3 本章示例代码的运行方法
首先添加 Maven
依赖:
<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>
然后在命令行执行命令:
mvn test -Dtest=SpecificTestClassName
本地实测时由于手动安装并配置了 Java11
,后续通过 IDEA
又安装了 Java21
和 Java24
等多个版本,导致上述命令报错,提示编译的版本不一致:
> 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
,与本机系统保持一致:
<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
:
// 1. use static
class SUTTest {// -- snip --@BeforeAllstatic void setUpClass() {resourceForAllTests = new ResourceForAllTests("Our resource for all tests");}// -- snip --
}// 2. use @TestInstance annotation
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SUTTest {// -- snip --@BeforeAllvoid setUpClass() {resourceForAllTests = new ResourceForAllTests("Our resource for all tests");}// -- snip --
}
2.5 @DisplayName 注解
该注解方便 IDEA
等 IDE
工具增强测试用例运行结果的可读性:
该注解的参数值支持文本、特殊字符、甚至是 emoji
表情符号,非常强大。
根据 IntelliJ IDEA
官方发布的 教学视频,可以创建自定义模板快速输入带 @DisplayName
注解的代码块:
另外,编辑变量可实现 TEST_NAME
和 METHOD_NAME
的联动:
实测备忘录
在测试类上加
@Disabled
注解后,直接运行该测试类,里面的方法仍然会执行。要让
IDEA
不执行该测试类,只能 从对应的包上 运行单元测试:> mvn test -Dtest="com/manning/junitbook/ch02/disabled/*"
JUnit 5
团队认为,测试代码是实现细节的一部分,通常不需要被外部代码所调用。将测试类的可见性降至包私有,更符合封装的原则,使得代码更加简洁。 ↩︎