junit5又名(junit功能)

junit5又名(junit功能)Java 语 的 xUnit 主流框架 JUnit Platform 用于 JVM 上启动测试框架的基础服务 提供命令行 IDE 和构建工具等方式执行测试的支持 不仅支持 Junit 自制的测试引擎 其他测试引擎也都可以接入 JUnit Jupiter JUnit Jupiter 提供了 JUnit5 的新的编程模型和扩展模型 是 JUnit5 新特性的核心 内部包含了一个测试引擎

大家好,我是讯享网,很高兴认识大家。





image
讯享网

Java 语⾔的 xUnit 主流框架:

image

  • JUnit Platform::用于 JVM 上启动测试框架的基础服务,提供命令行,IDE和构建工具等方式执行测试的支持。不仅支持 Junit 自制的测试引擎,其他测试引擎也都可以接入。
  • JUnit Jupiter:JUnit Jupiter 提供了 JUnit5 的新的编程模型和扩展模型,是 JUnit5 新特性的核心。内部包含了一个测试引擎,用于在 Junit Platform 上运行。
  • JUnit Vintage:由于 JUint 已经发展多年,为了照顾老的项目,JUnit Vintage 提供了兼容 JUnit4.x、Junit3.x 的测试引擎。

image

通过上述的介绍,不知道有没有发现 JUint5 似乎已经不再满足于安安静静做一个单元测试框架了,它的野心很大,想通过接入不同测试引擎,来支持各类测试框架的使用,成为一个基于 JVM 测试框架的基础平台。因此它也采用了分层的架构,分为了平台层、引擎层、框架层。下图可以很清晰地体现出来:

image

  • 最核心的就是平台层:IDE 和构建工具都是作为客户端和这个平台层交互,以达到在项目中运行测试的目的。TestEngine 的实现在平台层中用于发现和运行测试,并且输出测试报告,并通过平台层返回给客户端。
  • 核心关注点是扩展能力:不仅仅只是存在于测试类级别,在整个测试平台级别,都提供了足够的扩展能力。只需要实现框架本身对 TestEngine 的接口,任何测试框架都可以在 JUnit Platform 上运行,这代表着 JUnit5 将会有着很强的拓展性。只需要一点点工作,通过这一个扩展点,框架就能得到所有 IDE 和构建工具在测试上的支持。这对于新框架来说绝对是好事,在测试和构建这块的门槛更低。如 JUnit Vintage 就是一个 TestEngine 实现,用于执行 JUnit4 的测试。
  • 这些对于一个开发者来说意味着什么呢?这意味着一个测试框架和 JVM 开发市场上所有主流的工具集成的时候,你能更容易地说服你的经理、开发 leader、任何项阻碍你引入这个测试框架的人。

JUnit5 更像是 JUnit4 的一个超集,他提供了非常多的增强:

  • JUnit5 不再是单个库,而是模块化结构的集合。整个 API 分成了:自己的模块、引擎、Launcher、针对 Gradle 和 Surefire 的集成模块。
  • 更强大的断言功能和测试注解。
  • 嵌套测试类:不仅仅是 BDD(Behavior Driven Development)。
  • 动态测试:在运行时生成测试用例。
  • 扩展测试:JUnit5 提供了很多的标准扩展接口,第三方可以直接实现这些接口来提供自定义的行为。通过 @ExtendWith 注解可以声明在测试方法和类的执行中启用相应的扩展。
  • 支持 Hamcrest 匹配和 AssertJ 断言库,可以用它们来代替 JUnit5 的方法。
  • 实现了模块化,让测试执行和测试发现等不同模块解耦,减少依赖。
  • 提供对 Java8 的支持,如 Sream API、Lambda 表达式(允许你通过表达式来代替功能接口)等。
  • 提供了分组断言(允许执行一组断言,且会一起报告)。

迁移指南:

JUnit 平台可以通过 Jupiter 引擎来运行 JUnit 5 测试,通过 Vintage 引擎来运行 JUnit 3 和 JUnit 4 测试。因此,已有的 JUnit 3 和 4 的测试不需要任何修改就可以直接在 JUnit 平台上运行。只需要确保 Vintage 引擎的 jar 包出现在 classpath 中,JUnit 平台会自动发现并使用该引擎来运行 JUnit 3 和 4 测试。

开发人员可以按照自己的项目安排来规划迁移到 JUnit 5 的进度。可以保持已有的 JUnit 3 和 4 的测试用例不变,而新增加的测试用例则使用 JUnit 5。

在进行迁移的时候需要注意如下的变化:

  • 注解在 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

注解 说明 @Test 表示方法是测试方法(与 JUnit4 的 @Test 不同,它的职责非常单一,不能声明任何属性,拓展的测试将会由 Jupiter 提供额外注解) @ParameterizedTest 表示方法是参数化测试 @RepeatedTest 表示方法可重复执行 @DisplayName 为测试类或者测试方法设置展示名称 @BeforeEach 表示在每个测试方法之前执行 @AfterEach 表示在每个测试方法之后执行 @BeforeAll 只执行一次,执行时机是在所有测试方法和 @BeforeEach 注解方法之前 @AfterAll 只执行一次,执行时机是在所有测试方法和 @AfterEach 注解方法之后 @Tag 表示单元测试类别。类似于 JUnit4 中的 @Categories @Disabled 表示测试类或测试方法不执行。类似于 JUnit4 中的 @Ignore @Timeout 表示测试方法运行如果超过了指定时间将会返回错误 @ExtendWith 为测试类或测试方法提供扩展类引用
  • JUnit5 不再需要手动将测试类与测试方法为 public,包可见的访问级别就足够了。
  • 因为框架会为每个测试类创建一个单独的实例,且在 @BeforeAll/@AfterAll 方法执行时,尚无任何测试实例诞生。因此,这两个方法必须定义为静态方法。

示例:

  • Maven 依赖
 

讯享网
  • 测试代码
讯享网

执行结果:

 

JUnit5 使用了新的断言类:org.junit.jupiter.api.Assertions。相比之前的 Assert 断言类多了许多新的功能,并且大量方法支持 Java8 的 Lambda 表达式。

JUnit5 常用断言方法:

方法 说明 assertEquals(expected, actual) 查看两个对象是否相等。
(类似于字符串比较使用的 equals() 方法) assertNotEquals(first, second) 查看两个对象是否不相等。 assertNull(object) 查看对象是否为空。 assertNotNull(object) 查看对象是否不为空。 assertSame(expected, actual) 查看两个对象的引用是否相等。
(类似于使用“==”比较两个对象) assertNotSame(unexpected, actual) 查看两个对象的引用是否不相等。
(类似于使用“!=”比较两个对象) assertTrue(condition) 查看运行结果是否为 true。 assertFalse(condition) 查看运行结果是否为 false。 assertArrayEquals(expecteds, actuals) 查看两个数组是否相等。 assertThat(actual, matcher) 查看实际值是否满足指定的条件。 fail() 让测试执行失败。

以下为两个与 JUnit4 不太一样的断言方式。

JUnit5 提供了一种新的异常断言方式 Assertions.assertThrows(),配合函数式编程就可以进行使用。

我们先来考虑一下下面这个 JUnit4 测试:

讯享网

想象我们运行这个测试,如果传入到 execute() 方法中的参数是一个过去的时间,会正常抛出一个 IllegalArgumentException 异常。这种情况下,测试会运行通过。

但是如果在 buildTask() 方法中抛出了一个其他类型的异常呢?测试会正常执行,并且会提示你得到的异常和期望异常不匹配。这里问题就出来了,我们只是希望测试是在指定位置得到指定的异常,而不是在整个测试体中出现的异常都作为对比异常。

为此,在 JUnit5 中,提供了一个 assertThrows() 方法,可以非常轻松地处理这个问题:

 

同样的,Junit5 还提供了 Assertions.assertTimeout() 方法,为测试方法的指定位置,设置超时测试。

在这种情况下,就不会担心测试的 setup 阶段对代码执行时间的影响,你可以指定只去衡量某一段代码的执行时间。

另外还提供了一个选项:当出现超时的时候,是选择停止执行(即断言失败)还是继续当前测试(以衡量代码执行的真实完整时间)。

讯享网

问题现象:有⼀个⽅法存在多个断⾔,但是其中⼀个断⾔失败了,后⾯的断⾔都没有执⾏,难道我要等第⼀个问题修好了才能继续检查后⾯的断⾔么?

问题原因:因为原来使⽤的是 JUnit5 的普通断⾔,当⼀个断⾔失败会直接跳出测试⽅法,导致后⾯的断⾔⽆法执⾏,此时的脚本容错性较低。

解决思路

  • 拆开多个测试⽅法,每个测试⽅法进⾏⼀个断⾔。(会造成⼤量重复代码,此⽅案被否)
  • 使⽤软断⾔,即使⼀个断⾔失败,仍会进⾏进⾏余下的断⾔,然后统⼀输出所有断⾔结果。

实施⽅案:可以使⽤ JUnit5 提供的 Java8的断⾔⽅法,当⼀个断⾔失败,剩下的断⾔依然会执⾏,脚本的容错性增强。

Junit5 带来新的断⾔⽅式: 断⾔⽅法,会在执⾏完所有断⾔后统⼀输出结果,⼀次性暴露所有问题,提⾼了测试脚本的健壮性。

 

运行结果:

讯享网
 

在 JUnit4 中,如果想要实现参数化测试(使用不同的参数来测试相同的一个方法),只能使用测试类中的字段来实现。而在 JUnit5 中,提供了参数化测试来实现这个需求。不同的参数值可以直接和一个测试方法关联,并且允许直接在一个测试类中提供不同的参数值直接参与测试,这些在 JUnit4 中都是无法实现的。

JUnit5 的参数化可以通过一组 CSV 格式的字符串、外部的 CSV、YML、JSON 文件、枚举、工厂方法,或者指定的提供类来提供。CSV 中的字符串类型的值还可以自动地转化为指定的类型,并且可以完成自己的类型转换器,如将 String 转成你希望的任何指定类型。

  • @ValueSource:指定入参来源,支持八大基础类、String、Class 类型
  • @NullSource:提供一个 null 入参
  • @EnumSource:提供一个枚举入参
  • @MethodSource:通过一个方法入参(该方法实现了自定义的数据获取方式)
  • @CsvSource:提供 CSV 格式的入参
  • @CsvFileSource:通过 CSV 文件提供参数
  • @ArgumentsSource

测试类:

讯享网

执行结果:

image

测试类:

 

Yaml 相关依赖:

讯享网

测试类:

 

JUnit5 提供了嵌套测试用于更好表示各个单元测试类之间的关系。平时我们写单元测试时一般都是一个类对应一个单元测试类,不过有些互相之间有业务关系的类,他们的单元测试完全是可以写在一起。因此,使用内嵌的方式表示,能够减少测试类的数量,防止类爆炸。

JUnit5 提供了 @Nested 注解,能够以的形式对测试用例类进行逻辑分组。

示例:

讯享网

执行结果:

 

JUnit5 提供 @Disabled 禁用整个测试类或单个测试方法上的测试执行。

讯享网

重复运行单元测试可以更加保证测试的准确性,规避一些随机性带来的测试问题。

 

JUnit5 中的前置条件(Assumptions)类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。

前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要。在如下案例中:

  • assumeTrue 和 assumFalse 确保给定的条件为 true 或 false,不满足条件会使得测试方法执行终止。
  • assumingThat 的参数是分别表示条件的布尔值和 Executable 接口的实现对象。只有条件满足时,Executable 对象才会被执行;当条件不满足时,测试方法的执行并不会终止。
讯享网

以下展示如何通过 MethodOrderer 类控制 JUnit5 的测试执行顺序。

示例:

 

执行结果:

讯享网

示例:

 

执行结果:

讯享网

示例:

 

还可配置自定义种子 junit.jupiter.execution.order.random.seed 以创建可重复的测试版本:

  • 方式一:在 junit-platform.properties 属性文件中配置
讯享网
  • 方式二:在 Maven 的 pom.xml 中配置参数
 

示例:

讯享网

执行结果:

image


问题场景:运维团队有⼀批做线上配置检查脚本,领导希望将他们的测试结果整合到我们的 Junit 测试报告⾥,他们有⼏千条测试⽤例,⽽且是 shell 写成,使⽤ Java 重写⼯作量巨⼤。

问题原因:传统⾃动化测试思路中,我们的测试逻辑是在以硬编码的形式组织到代码⾥的,当遇到⽤例迁移或结果整合时,会产⽣⼤量的逻辑重写。

解决思路:除了硬编码的脚本编写⽅式外,还要能动态地在脚本 Runtime 时⽣成⽤例。

实施⽅案:JUnit5 提供了动态测试⽅案,让测试⼈员可以在脚本 Runtime 时动态的批量⽣成⽤例。

官⽅给出的 DynamicTest ⽰例

image

案例实现

  • Maven 依赖:
 
  • 配置文件:shell_test_result.yaml
讯享网
  • 实体类:ShellResult.java
 
  • 实体类:ResultList.java
讯享网
  • 测试类:
 
  • 执行结果:

image


默认情况下,JUnit Jupiter 测试是在单个线程中按顺序运行的。自 5.3 版起,作为可选功能,可以并发执行测试。

并发测试前提条件:测试用例之间没有依赖关系,容错性好。

Junit5 的并发测试是在 junit-platform.properties 文件中进行配置的,只要在 src/main/resources/ 目录下新建该文件,那么 Junit5 在执行测试方法时就会自动读取配置文件中的配置。

src/main/resources/junit-platform.properties 文件内容:

讯享网

测试程序:

 

Junit5 官方 User guide 对每个配置项进行了简单的解释:

讯享网

要启用并发执行,请将以上配置参数设置为 true。

 

以上两个配置项是用来控制测试脚本是否在方法维度和类维度进行并发执行。它们具有相同的两个配置选项,官方 User guide 解释如下:

  • :强制与前置方法使用的同一线程执行。例如,当在测试方法上使用时,该测试方法将在 @BeforeAll 或 @AfterAll 方法的线程中执行。
  • :并发执行,除非资源锁强制在同一线程中执行。

说白了就是 SAME_THREAD 意味着单线程,而 CONCURRENT 意味着多线程。

官方 User guide 中有一个图来解读这两个配置项组合能达到什么样的效果:

image

线程池配置的三种方式

剩下这两个配置是用来控制线程池属性的:

讯享网
  1. :根据可用逻辑处理器数量乘以 junit.jupiter.execution.parallel.config.dynamic.factor 的配置参数(默认为 1)计算并行的线程池数量。也就是说配置一个固定的倍数后,框架会根据运行机器的算力自动配置线程。
  2. :使用 junit.jupiter.execution.parallel.config.fixed.parallelism 的配置参数作为并行的线程池数量。
  3. :允许通过实现接口 ParallelExecutionConfigurationStrategy 来配置并行的线程池数量,junit.jupiter.execution.parallel.config.custom.class 属性用来配置实现接口的实现类。

使用 JUnit5 测试套件,可以将测试扩展到多个测试类和不同的软件包。

JUnit5 提供了两个注解:@SelectPackages 和 @SelectClasses 来创建测试套件。而要执行该套件,需要配合使用 @RunWith(JUnitPlatform.class)。

注解 作用 @RunWith(JUnitPlatform.class) 测试套件(从 JUnit4 迁移过来的) @SelectPackage 创建测试套件 @SelectClasses 创建测试套件 @IncludePackage 过滤需要执行的测试包 @ExcludePackages 过滤不需要执行的测试包 @IncludeClassNamePatterns 过滤需要执行的测试类 @ExcludeClassNamePatterns 过滤不需要执行的测试类 @IncludeTags 过滤需要执行的测试方法 @ExcludeTags 过滤不需要执行的测试方法

添加 Maven 依赖:

 

示例:@RunWith、@SelectPackages

讯享网

image


示例:@SelectPackages、@SelectClasses

 

image


示例:@IncludePackages、@ExcludePackages

讯享网

image


示例:@IncludeClassNamePatterns、@ExcludeClassNamePatterns

 

image


示例:@IncludeTags、@Tag

讯享网

image


如果你执行过 mvn test 或者执行其他 maven 命令时跑了测试用例,你就已经用过 maven-surefire-plugin 了。maven-surefire-plugin 是 maven 里执行测试用例的插件,不显示配置就会用默认配置。这个插件的 surefire:test 命令会默认绑定 maven 执行的 test 阶段。

maven的生命周期有哪些阶段?

[validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy]

如果说 maven 已经有了 maven-surefire-plugin 的默认配置,我们还有必要了解 maven-surefire-plugin 的配置么?答案是肯定的。虽说 maven-surefire-plugin 有默认配置,但是当需要修改一些测试执行的策略时,就有必要我们去重新配置这个插件了。

插件自动匹配

最简单的配置方式就不配置或者是只声明插件。

 

这个时候 maven-surefire-plugin 会按照如下逻辑去寻找 JUnit 的版本并执行测试用例。

讯享网

插件手动匹配

示例:

 

更多用法

maven-surefire-plugin 更多用法

小讯
上一篇 2025-05-31 08:26
下一篇 2025-06-11 18:00

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/198500.html