从JUnit4迁移到JUnit5:重要的区别和好处
目录
- JUnit5简述
- 主要区别
- 路径
- 注解
- 断言
- 假设
- JUnit的扩展
- 换成JUnit5
- 新特性
- 定义描述信息
- 断言
- @Nested
- @ParameterizedTest
- 条件执行
- 测试模板
- 动态测试
Migrating from JUnit 4 to JUnit 5: Important Differences and Benefits
JUnit5简述
适应软件工程的发展,JUnit5在先前版本上演化出来,功能改进和提供新特性,为了更好的服务于测试。一般使用而言:只需更新依赖项即可。
JUnit5提供了Vintage
库运行JUnit4的测试而无需对测试用例做任何修改。
junit-vintage-engine 是 JUnit 4 中使用的测试引擎
junit-jupiter-engine 是 JUnit 5 中使用的测试引擎
看完以下四点介绍,再决定是否使用JUnit5也不迟:
- 使用了java语言高版本的特性,如lambda函数。使得测试更强大也更易于维护;
- 为描述、组织、执行测试添加了一些非常有用的新特性,例如,测试可以获得更好的显示名称,并且可以分层组织;
- 按照特性分成独立的依赖包,使用中只需导入需要的特性依赖即可,如使用Maven和Gradle构建的工程,导入依赖是很方便的;
- 可以同时使用多个扩展,而JUnit4一次只能使用一个runner,这意味着可以很容易的将Spring扩展和其他扩展结合起来;
从JUnit4切换到JUnit5不是很麻烦,对不使用新特性而言,一般无需对旧的测试用例做多少更改,切换步骤如下:
- 更新依赖项(maven或gradle的配置文件),注意要保留
junit-vintage-engine
依赖以运行JUnit4的测试用例; - 新的测试用例可以使用JUnit5构建编写了;
主要区别
两者使用起来差别不大,一些需要额外留意的如下:
路径
JUnit 5 使用新的包结构org.junit.jupiter
.如org.junit.Test
换成org.junit.jupiter.api.Test
注解
注解@Test
不再有参数,参数移到方法体中。
如JUnit4中测试预期抛出异常样例:
@Test(expected = Exception.class)
public void testThrowsException() throws Exception {// ...
}
在JUnit5中,使用如下:
@Test
void testThrowsException() throws Exception {Assertions.assertThrows(Exception.class, () -> {//...});
}
同样的,常用参数timeout
在JUnit4中如下:
@Test(timeout = 10)
public void testFailWithTimeout() throws InterruptedException {Thread.sleep(100);
}
在JUnit5中,使用如下:
@Test
void testFailWithTimeout() throws InterruptedException {Assertions.assertTimeout(Duration.ofMillis(10), () -> Thread.sleep(100));
}
常用注解变动如下:
JUnit4 | JUnit5 |
---|---|
@Before | @BeforeEach |
@After | @AfterEach |
@BeforeClass | @BeforeAll |
@AfterClass | @AfterAll |
@Ignore | @Disabled |
@Category | @Tag |
@Rule
和 @ClassRule
使用 @ExtendWith
和 @RegisterExtension
替代。
断言
JUnit5中断言路径是org.junit.jupiter.api.Assertions
。多数常见断言,如assertEquals()
,assertNotNull()
,虽然看起来没变,但是存在一些变动:
- 参数中错误信息移到最后,如
assertEquals("error msg", 1, 2)
变成assertEquals(1, 2, "error msg")
- 多数断言支持lambda形式的错误信息,在断言失败的时候调用;
assertTimeout()
和assertTimeoutPreemptively()
取代JUnit4中的@Timeout
注解(JUnit5中的@Timeout
注解功能作用和JUnit4中的@Timeout
是不一样的).
假设
假设的包路径是org.junit.jupiter.api.Assumptions
。支持先前的假设及使用,同时提供了支持BooleanSupplier
及Hamcrest matchers匹配条件,支持条件匹配上执行lambda表达式。如JUnit4中的一个例子:
@Test
public void testNothingInParticular() throws Exception {Assume.assumeThat("foo", is("bar"));assertEquals(...);
}
在JUnit5中可以写成如下:
@Test
void testNothingInParticular() throws Exception {Assumptions.assumingThat("foo".equals(" bar"), () -> {assertEquals(...);});
}
JUnit的扩展
在JUnit4中,一般使用注解@RunWIth
指定运行环境,是JUnit提供给其他框架测试环境接口扩展。使用多个运行器是有问题的,通常需要chaining
或者注解@Rule
。在JUnit5中对扩展进行了简化和改进。
在JUnit4中使用spring框架构建测试如下:
@RunWith(SpringJUnit4ClassRunner.class)
public class MyControllerTest {// ...
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface RunWith {Class<? extends Runner> value();
}
在JUnit5中使用Spring extension
替代:
@ExtendWith(SpringExtension.class)
class MyControllerTest {// ...
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Repeatable(Extensions.class)
@API(status = Status.STABLE,since = "5.0"
)
public @interface ExtendWith {Class<? extends Extension>[] value();
}
注解@ExtendWith
是可重复的, 意味着多个扩展可以方便的组合在一起。
如何自定义扩展呢?
通过实现包org.junit.jupiter.api.extension
里的一个或多个接口,然后使用注解@ExtendWith
添加到测试样例中。
换成JUnit5
将JUnit4测试用例转换到JUnit5,对多数用例而言一般步骤如下:
- 修改包名路径,移除JUnit4,换成JUnit5。如注解
@Test
的路径,Asserts
改成Assertions
等; - 全局替换注解和类名,如
@Before
换成@BeforeEach
,就使用IDE工具而言,更换了依赖后,旧的注解或类名会有错误提示的; - 注意
assertions
(消息参数移到最后),timeout
,expected exceptions
,具体见上文说明; - 更新
assumptions
; - 用注解
@ExtendWith
替换@RunWith
、@Rule
或@ClassRule
,以及解决替换后的问题;
Note that migrating parameterized tests will require a little more refactoring, especially if you have been using JUnit 4
Parameterized
(the format of JUnit 5 parameterized tests is much closer toJUnitParams
).
新特性
上文说明的是已有的特性功能及变动,JUnit5还提供了不少新的特性,让测试用例的更具有描述性和维护性。
定义描述信息
可以在类或方法中使用注解@DisplayName
定义描述信息,使得描述测试的目的和追踪失败更容易,如:
@DisplayName("Test MyClass")
class MyClassTest {@Test@DisplayName("Verify MyClass.myMethod returns true")void testMyMethod() throws Exception { // ...}
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = Status.STABLE,since = "5.0"
)
public @interface DisplayName {String value();
}
更多信息:See the JUnit document for specifics and examples.
断言
JUnit5提供了新的断言,如下:
- assertIterableEquals() 对
Iterable<?>
遍历equals(),如果元素是Iterable
递归继续; - assertLinesMatch() 对字符列表(list,stream)匹配;
- assertAll() 所有断言一起执行,失败的不影响其他执行;
- assertThrows() 和assertDoesNotThrow() 替代注解
@Test
里的expected property
@Nested
允许你有一个内部类,它本质上是一个测试类,允许你在下面组合几个测试类相同的父级(具有相同的初始化,如:
@DisplayName("Verify MyClass")
class MyClassTest {MyClass underTest;@Test@DisplayName("can be instantiated")public void testConstructor() throws Exception { new MyClass();}@Nested@DisplayName("with initialization")class WithInitialization {@BeforeEachvoid setup() {underTest = new MyClass();underTest.init("foo");}@Test@DisplayName("myMethod returns true")void testMyMethod() {assertTrue(underTest.myMethod());}}
}
使用displayname
在测试报告中描述测试的目的以及结构关系
@ParameterizedTest
JUnit4中已经存在,内置的如JUnit4Parameterized
或者第三方的JUnitParams
。而在JUnit5中,借鉴两者好的特性以此完全内置了。如下:
@ParameterizedTest
@ValueSource(strings = {"foo", "bar"})
@NullAndEmptySource
void myParameterizedTest(String arg) {underTest.performAction(arg);
}
形式看起来类似JUnitParams
,参数直接传递给测试方法。需要注意测试的值可以来自多个不同的源。例子中只用了一个参数,所以@ValueSource
很方便。还有@EmptySource
空字符,@NullSource
空值,其他的还有如@EnumSource
、@ArgumentsSource
,多参数的如@MethodSource
、@CsvSource
另一个添加的测试类型是@RepeatedTest
,一个测试重复执行指定次数。
条件执行
JUnit5提供了ExecutionCondition
扩展api来有条件的启用或停用一个测试或类。如同在测试上使用注解@Disabled
一样,这里提供了判断条件。内置的条件如下:
- @EnabledOnOs 和@DisabledOnOs: 指定的操作系统
- @EnabledOnJre and @DisabledOnJre: 指定的jre版本
- @EnabledIfSystemProperty: 如果满足JVM系统属性值启用
- @EnabledIf: 如果If条件满足启用
测试模板
测试模板不是常规测试;它们定义了一组要执行的步骤,然后可以在其他地方使用特定的调用上下文执行。 For details and examples, see the documentation.
动态测试
动态测试就像测试模板,要运行的测试是在运行时生成的。然而,测试模板是用一组特定的步骤来定义并运行多次,而动态测试使用相同的调用上下文,但可以执行不同的逻辑。动态测试的一个用途是将一个抽象对象的列表流化,并根据它们的具体类型为每个对象执行一组单独的断言。There are good examples in the documentation.
从JUnit4迁移到JUnit5:重要的区别和好处相关推荐
- 迁移学习和finetune的区别及迁移学习代码实现
转载:https://blog.csdn.net/gentelyang/article/details/77512565 一:区别 1:迁移学习是将已经学习到的知识应用到其他领域,比如通用的语音模型迁 ...
- 迁移学习与微调的区别
一.迁移学习: 1.从字面意义上理解是知识转移的学习方法,指一种学习方法:类比机器学习.深度学习等等概念: 2.把已训练好的模型参数迁移到新的模型来帮助新模型训练 二.微调: 1.从字面意义上理解是小 ...
- java基本类型封装类和原始类型的区别及好处
这是最近有人问我的一个问题,我当时解答了,但是发现解答的并不是很全面,所以花时间稍微整理了一下 我们先来看一下java的基本类型和其封装类 原始类型 封装类 bool ...
- JUnit4和JUnit5的主要区别
JUnit5的目标是采用Java8的编程风格并且比JUnit4更加健壮和灵活.在这篇博客中,我们将关注一些JUnit4和JUnit5的主要区别. 1.不同的注解 大部分注解在JUnit4和JUnit5 ...
- junit5和junit4_JUnit 5 –设置
junit5和junit4 2015年11月, JUnit Lambda团队展示了他们的原型 . 此后,该项目更名为JUnit 5,并于2016年2月发布了Alpha版本.我们将在一系列简短文章中进行 ...
- Springboot-21单元测试(Junit5、assertions、assumptions、嵌套测试、参数化测试)
1.JUnit5 的变化 Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库 作为最新版本的JUnit框架由,三个不同子项目的几个不同模块组成. JUnit 5 = ...
- 网络编程中设计并发服务器,使用多进程 与 多线程 ,请问有什么区别?
为什么80%的码农都做不了架构师?>>> 答案一: 1,进程:子进程是父进程的复制品.子进程获得父进程数据空间.堆和栈的复制品. 2,线程:相对与进程而言,线程是一个更加接近与执行体 ...
- 迁移学习(transfer learning)与finetune的关系?【finetune只是transfer learning的一种手段】
目录 1.迁移学习简介 2.为什么要迁移学习? 3.迁移学习的几种方式 1)Transfer Learning: 2)Extract Feature Vector: 3)Fine-tune: 4.三种 ...
- 连载二:Oracle迁移文章大全
(共45篇干货文章,建议收藏并在PC端打开) 1. ASM新加DG,数据文件如何迁移 https://www.modb.pro/db/307 2. AIX环境dd迁移控制文件出现ORA-202和ORA ...
- 数据传输服务 DTS > 数据迁移 > 支持的数据库和迁移类型
支持的数据库和迁移类型 更新时间:2020-09-27 09:16:28 编辑我的收藏 本页目录 优惠活动 迁移类型说明 支持的数据库及迁移类型 数据迁移功能帮助您实现同构或异构数据源之间的数据迁移, ...
最新文章
- 分布式服务限流实战,已经为你排好坑了
- python minimize_简单三步实现Python脚本超参数调优(附代码)
- Actipro WPF Studio破解
- 美国正式宣告将在月球建立永久存在基地
- !important------至高无上的宝剑
- Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍
- python推荐系统-RecQ-Python推荐系统框架
- ipython怎么安装_ipython的两种安装方式
- 什么是全兼容?DVD主流格式全面解析
- 【操作系统/OS笔记15】死锁的系统模型,死锁的处理办法,银行家算法与死锁检验算法
- 单细胞----关于Seurat的一些知识
- 遇到 java.io.EOFException 异常的解决办法
- win8.1能安装matlab,解决win8.1安装matlab出现无法访问您试图使用的功能...vcredist.msc...等等...
- 在iOS7中修改键盘Return键的类型
- python学习(五)--打印错误信息
- 简笔画花边边框超简单_花边简笔画简单又漂亮 手抄报的边框图片大全
- 由KKT互补松弛条件,支持向量的系数不一定为0,非支持向量的系数一定为0
- 一次服务器时间调整引发的实例宕机
- IOS开发环境 Xcode 下载 安装
- java程序设计有理数,《Java程序设计》复习题
热门文章
- CAD教程:CAD自定义菜单和工具栏的操作技巧
- 【软件应用开发】小米便签APP维护开发
- 元分析教程 | 手把手教你使用CMA 2.0
- 游程编码解密(C语言详解)
- 负载均衡(负载平衡)
- python源码提取_从PyInstaller打包生成的EXE文件中提取Python源码
- mtk平台sensor分析一:alsps框架下的光距感驱动流程
- Masscan工具使用
- MAX485芯片介绍(MAX485ESA+T,半双工RS422和RS485串口收发传输芯片,2.5Mbps传输速率。5V逻辑电平)
- 【python】Anaconda3环境安装