目录

  • 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(消息参数移到最后),timeoutexpected 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 to JUnitParams).

新特性

上文说明的是已有的特性功能及变动,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:重要的区别和好处相关推荐

  1. 迁移学习和finetune的区别及迁移学习代码实现

    转载:https://blog.csdn.net/gentelyang/article/details/77512565 一:区别 1:迁移学习是将已经学习到的知识应用到其他领域,比如通用的语音模型迁 ...

  2. 迁移学习与微调的区别

    一.迁移学习: 1.从字面意义上理解是知识转移的学习方法,指一种学习方法:类比机器学习.深度学习等等概念: 2.把已训练好的模型参数迁移到新的模型来帮助新模型训练 二.微调: 1.从字面意义上理解是小 ...

  3. java基本类型封装类和原始类型的区别及好处

    这是最近有人问我的一个问题,我当时解答了,但是发现解答的并不是很全面,所以花时间稍微整理了一下 我们先来看一下java的基本类型和其封装类 原始类型           封装类        bool ...

  4. JUnit4和JUnit5的主要区别

    JUnit5的目标是采用Java8的编程风格并且比JUnit4更加健壮和灵活.在这篇博客中,我们将关注一些JUnit4和JUnit5的主要区别. 1.不同的注解 大部分注解在JUnit4和JUnit5 ...

  5. junit5和junit4_JUnit 5 –设置

    junit5和junit4 2015年11月, JUnit Lambda团队展示了他们的原型 . 此后,该项目更名为JUnit 5,并于2016年2月发布了Alpha版本.我们将在一系列简短文章中进行 ...

  6. Springboot-21单元测试(Junit5、assertions、assumptions、嵌套测试、参数化测试)

    1.JUnit5 的变化 Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库 作为最新版本的JUnit框架由,三个不同子项目的几个不同模块组成. JUnit 5 = ...

  7. 网络编程中设计并发服务器,使用多进程 与 多线程 ,请问有什么区别?

    为什么80%的码农都做不了架构师?>>> 答案一: 1,进程:子进程是父进程的复制品.子进程获得父进程数据空间.堆和栈的复制品. 2,线程:相对与进程而言,线程是一个更加接近与执行体 ...

  8. 迁移学习(transfer learning)与finetune的关系?【finetune只是transfer learning的一种手段】

    目录 1.迁移学习简介 2.为什么要迁移学习? 3.迁移学习的几种方式 1)Transfer Learning: 2)Extract Feature Vector: 3)Fine-tune: 4.三种 ...

  9. 连载二:Oracle迁移文章大全

    (共45篇干货文章,建议收藏并在PC端打开) 1. ASM新加DG,数据文件如何迁移 https://www.modb.pro/db/307 2. AIX环境dd迁移控制文件出现ORA-202和ORA ...

  10. 数据传输服务 DTS > 数据迁移 > 支持的数据库和迁移类型

    支持的数据库和迁移类型 更新时间:2020-09-27 09:16:28 编辑我的收藏 本页目录 优惠活动 迁移类型说明 支持的数据库及迁移类型 数据迁移功能帮助您实现同构或异构数据源之间的数据迁移, ...

最新文章

  1. 分布式服务限流实战,已经为你排好坑了
  2. python minimize_简单三步实现Python脚本超参数调优(附代码)
  3. Actipro WPF Studio破解
  4. 美国正式宣告将在月球建立永久存在基地
  5. !important------至高无上的宝剑
  6. Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍
  7. python推荐系统-RecQ-Python推荐系统框架
  8. ipython怎么安装_ipython的两种安装方式
  9. 什么是全兼容?DVD主流格式全面解析
  10. 【操作系统/OS笔记15】死锁的系统模型,死锁的处理办法,银行家算法与死锁检验算法
  11. 单细胞----关于Seurat的一些知识
  12. 遇到 java.io.EOFException 异常的解决办法
  13. win8.1能安装matlab,解决win8.1安装matlab出现无法访问您试图使用的功能...vcredist.msc...等等...
  14. 在iOS7中修改键盘Return键的类型
  15. python学习(五)--打印错误信息
  16. 简笔画花边边框超简单_花边简笔画简单又漂亮 手抄报的边框图片大全
  17. 由KKT互补松弛条件,支持向量的系数不一定为0,非支持向量的系数一定为0
  18. 一次服务器时间调整引发的实例宕机
  19. IOS开发环境 Xcode 下载 安装
  20. java程序设计有理数,《Java程序设计》复习题

热门文章

  1. CAD教程:CAD自定义菜单和工具栏的操作技巧
  2. 【软件应用开发】小米便签APP维护开发
  3. 元分析教程 | 手把手教你使用CMA 2.0
  4. 游程编码解密(C语言详解)
  5. 负载均衡(负载平衡)
  6. python源码提取_从PyInstaller打包生成的EXE文件中提取Python源码
  7. mtk平台sensor分析一:alsps框架下的光距感驱动流程
  8. Masscan工具使用
  9. MAX485芯片介绍(MAX485ESA+T,半双工RS422和RS485串口收发传输芯片,2.5Mbps传输速率。5V逻辑电平)
  10. 【python】Anaconda3环境安装