JUnit 5 –基础

JUnit 5是适用于Java的下一代单元测试框架,具有许多有趣的功能,包括嵌套测试,参数化测试,新的扩展API或Java 8支持。

本文展示了JUnit 5的基本概念,包括测试生命周期,参数注入和断言(基本,超时和异常)。

文献资料

首先,我认为JUnit 5文档很棒。 它不仅包含全面的框架文档,还包含许多示例,包括许多示例。 学习JUnit 5时请不要错过文档: http : //junit.org/junit5/docs/current/user-guide/

依存关系

首先,JUnit 5需要Java 8才能运行。 最后。 这带来了在测试中使用Lambda表达式的可能性,并使它们更加简洁(Lambda表达式主要用于断言中)。 其次,JUnit 5由按JUnit平台,JUnit Jupiter和JUnit Vintage分组的多个工件组成。 这听起来可能很吓人,但是如今使用Maven或Gradle之类的工具根本不是问题,要开始使用,您实际上只需要一个依赖项。 Gradle的基本配置如下所示:

buildscript {ext {junitPlatformVersion = '1.0.1'junitJupiterVersion = '5.0.1'}repositories {mavenCentral()}dependencies {classpath "org.junit.platform:junit-platform-gradle-plugin:${junitPlatformVersion}"}
}apply plugin: 'java'
apply plugin: 'org.junit.platform.gradle.plugin'sourceCompatibility = 1.8repositories {mavenCentral()
}dependencies { testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
}task wrapper(type: Wrapper) {gradleVersion = '4.1'
}

JUnit 5测试类和方法

在测试类(从org.junit.jupiter.api导入)中使用的常见测试注释是:

  • @BeforeAll –在测试类中的所有方法之前执行
  • @BeforeEach –在测试类中的每个测试方法之前执行
  • @Test –实际测试方法
  • @AfterEach –在测试环境中的每个测试方法之后执行
  • @AfterAll –在测试过程中的所有方法之后执行

其他基本但有用的注释:

  • @DisplayName –测试类或方法的自定义显示名称
  • @Disabled –禁用测试类或方法
  • @RepeatedTest –用测试方法制作测试模板
  • @Tag –标记测试类或方法以进一步选择测试

一个基本的例子:

import org.junit.jupiter.api.*;@DisplayName("JUnit5 - Test basics")
class JUnit5Basics {@BeforeAllstatic void beforeAll() {System.out.println("Before all tests (once)");}@BeforeEachvoid beforeEach() {System.out.println("Runs before each test");}@Testvoid standardTest() {System.out.println("Test is running");}@DisplayName("My #2 JUnit5 test")@Testvoid testWithCustomDisplayName() {System.out.println("Test is running");}@DisplayName("Tagged JUnit5 test ")@Tag("cool")@Testvoid tagged() {System.out.println("Test is running");}@Disabled("Failing due to unknown reason")@DisplayName("Disabled test")@Testvoid disabledTest() {System.out.println("Disabled, will not show up");}@DisplayName("Repeated test")@RepeatedTest(value = 2, name = "#{currentRepetition} of {totalRepetitions}")void repeatedTestWithRepetitionInfo() {System.out.println("Repeated test");}@AfterEachvoid afterEach() {System.out.println("Runs after each test");}
}

注意,测试类和方法不必是公共的 ,它们可以是包私有的

测试执行生命周期

在JUnit 5中,默认情况下会为测试类中的每个测试方法创建一个新的测试实例。 可以使用类级别@TestInstance注释来调整此行为:

import org.junit.jupiter.api.*;@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@DisplayName("JUnit5 - Test lifecycle adjustments")
class JUnit5PerClassLifecycle {private Object first = new Object();private Object second;@BeforeAllvoid beforeAll() {this.second = this.first;System.out.println("Non static before all.");}@BeforeEachvoid beforeEach() {Assertions.assertEquals(first, second);}@Testvoid first() {Assertions.assertEquals(first, second);}@Testvoid second() {Assertions.assertEquals(first, second);}@AfterAllvoid afterAll() {System.out.println("Non static after all.");}@AfterEachvoid afterEach() {Assertions.assertEquals(first, second);}
}

PER_CLASS模式下,将为所有测试创建单个测试实例,并且@BeforeAll@AfterAll方法不再需要是静态的。

参数解析

测试和回调方法现在可以采用org.junit.jupiter.api.TestInfoorg.junit.jupiter.api.RepetitionInfoorg.junit.jupiter.api.TestReporter类的参数。

另外,由于使用了非常简单但功能强大的JUnit 5扩展API,因此在方法中解析自定义参数只需提供自己的org.junit.jupiter.api.extension.ParameterResolver实现即可。

class JUnit5BuiltInParameterResolution {@BeforeAllstatic void beforeAll(TestInfo testInfo) {System.out.println("Before all can take parameters. Started: " + testInfo.getDisplayName());}@BeforeAllstatic void beforeAll(TestReporter testReporter) {testReporter.publishEntry("myEntry", "myValue");}@BeforeAllstatic void beforeAll(TestInfo testInfo, TestReporter testReporter) {testReporter.publishEntry("myOtherEntry", testInfo.getDisplayName());}@BeforeEachvoid beforeEach(TestInfo testInfo) {}@Testvoid standardTest(TestInfo testInfo) {}@DisplayName("Repeated test")@RepeatedTest(value = 2, name = "#{currentRepetition} of {totalRepetitions}")void repeatedTest(RepetitionInfo repetitionInfo) {System.out.println("Repeated test - " + repetitionInfo.toString());}@AfterAllstatic void afterAll() {}@AfterAllstatic void afterAll(TestInfo testInfo) {}@AfterEachvoid afterEach() {}
}

断言

JUnit 5带有许多标准断言,可以在org.junit.jupiter.api.Assertions类中找到。

基本断言

基本主张是: assertEqualsassertArrayEqualsassertSameassertNotSameassertTrueassertFalseassertNullassertNotNullassertLinesMatchassertIterablesMatch

例:

@Test
void basicAssertions() {// arrangeList<String> owners = Lists.newArrayList("Betty Davis", "Eduardo Rodriquez");// assertassertNotNull(owners);assertSame(owners, owners);assertFalse(owners::isEmpty); // Lambda expressionassertEquals(2, owners.size(), "Found owner names size is incorrect");assertLinesMatch(newArrayList("Betty Davis", "Eduardo Rodriquez"), owners);assertArrayEquals(new String[]{"Betty Davis", "Eduardo Rodriquez"}, owners.toArray(new String[0]));
}

断言所有

Assertions.assertAll断言所有提供的可执行文件均不会引发异常:

Assertions.assertAll(() -> Assertions.assertNotNull(null, "May not be null"),() -> Assertions.assertTrue(false, "Must be true")
);

上面将报告多个失败:

org.opentest4j.MultipleFailuresError: Multiple Failures (2 failures)May not be null ==> expected: not <null>Must be true

注意:您可能想阅读有关JUnit 4和AssertJ中的替代方法的信息-http: //blog.codeleak.pl/2015/09/assertjs-softassertions-do-we-need-them.html

超时断言

使用超时断言来验证未超过任务的执行时间。 超时断言有两种: assertTimeoutassertTimeoutPreemptively 。 都拿两个

  • 同步执行任务,等待任务完成,然后声明超时:
@Test
void assertTimeout() {// arrangeExecutable task = () -> Thread.sleep(1000);// waits for the task to finish before failing the testAssertions.assertTimeout(Duration.ofMillis(100), task::execute);
}@Test
void assertTimeoutWithThrowingSupplier() {// arrangeThrowingSupplier<String> task = () -> "result";// waits for the task to finish before failing the testAssertions.assertTimeout(Duration.ofMillis(100), task::get);
}
  • 异步执行任务(在新线程中),到超时时中止执行:
@Test
void assertTimeoutPreemptively() {// arrangeExecutable task = () -> Thread.sleep(1000);// abort execution when timeout exceededAssertions.assertTimeoutPreemptively(Duration.ofMillis(100), task::execute);
}@Test
void assertTimeoutPreemptivelyWithThrowingSupplier() {// arrangeThrowingSupplier<String> task = () -> "result";// abort execution when timeout exceeded, return the resultString result = Assertions.assertTimeoutPreemptively(Duration.ofMillis(100), task::get);Assertions.assertEquals("result", result);
}

异常断言

JUnit 5内置的assertThrows获取预期的异常类型作为第一个参数,而可执行文件(功能接口)则可能将异常作为第二个参数。 如果未引发任何异常或其他类型的异常,则该方法将失败。 该方法返回异常本身,该异常可用于进一步的声明:

@Test
void assertException() {// arrangeExecutable throwingExecutable = () -> {throw new RuntimeException("Unexpected error!");};// act and assertRuntimeException thrown = Assertions.assertThrows(RuntimeException.class, throwingExecutable::execute, "???");Assertions.assertAll(() -> Assertions.assertEquals("Unexpected error!", thrown.getMessage()),() -> Assertions.assertNotNull(thrown.getCause()));
}

注意:您可能想阅读有关JUnit 4中的替代方法的信息-http: //blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html

摘要

JUnit 5具有许多功能。 在本文中,仅演示了基础知识,但这足以让您开始编写第一个JUnit 5测试。

也可以看看

  • 使用JUnit 5进行更清洁的参数化测试– http://blog.codeleak.pl/2017/06/cleaner-parameterized-tests-with-junit-5.html

翻译自: https://www.javacodegeeks.com/2017/10/junit-5-basics-2.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql explain output_MySQL查询优化之explain的深入解析【转载】

在分析查询性能时&#xff0c;考虑EXPLAIN关键字同样很管用。EXPLAIN关键字一般放在SELECT查询语句的前面&#xff0c;用于描述MySQL如何执行查询操作、以及MySQL成功返回结果集需要执行的行数。explain 可以帮助我们分析 select 语句,让我们知道查询效率低下的原因,从而改进我…

char强制类型转换为int_C语言学习第5篇---类型转换概念理解

类型之间的转换1.C语言中的数据可以进行转换---强制类型转换---隐式类型转换强制类型转换1.强制类型转换的语法---&#xff08;Type&#xff09;var_name;---&#xff08;Type&#xff09;value;2.强制类型转换的结果---目标类型能够容纳目标值&#xff0c;结果不变---目标类型…

python 中求最大值问题_Python中用max()方法求最大值的介绍

max() 方法返回其参数最大值&#xff1a;最接近正无穷大的值。语法以下是max()方法的语法&#xff1a; max( x, y, z, .... )参数 x -- 这是一个数值表达式。 y -- 这也是一个数值表达式。 z -- 这是一个数值表达式。返回值此方法返回其参数的最大值。例子下面的例子显示了max(…

在项目中使用fastreport_如何在项目管理中使用里程碑

不管您的项目是什么&#xff0c;完成大工作都意味着朝目标端点迈出几步。正如您无法结束旅程一样&#xff0c;您的团队必须完成第一步&#xff0c;以便从下一个步骤开始并最终完成项目。这可能是设定里程碑的最大原因。毕竟&#xff0c;如果没有完成日期&#xff0c;则项目的一…

java nio的演进_Java接口的防御性API演进

java nio的演进API的发展绝对是不平凡的。 只有少数几个需要处理的事情。 我们大多数人每天都在使用内部专有API。 现代IDE附带了很棒的工具&#xff0c;可以分解&#xff0c;重命名&#xff0c;上拉&#xff0c;下推&#xff0c;间接&#xff0c;委托&#xff0c;推断&#xf…

python层次聚类法画图_Python实现简单层次聚类算法以及可视化

本文实例为大家分享了Python实现简单层次聚类算法&#xff0c;以及可视化&#xff0c;供大家参考&#xff0c;具体内容如下基本的算法思路就是&#xff1a;把当前组间距离最小的两组合并成一组。算法的差异在算法如何确定组件的距离&#xff0c;一般有最大距离&#xff0c;最小…

range函数python2和3区别_【后端开发】range函数python2和3区别

range函数是一个用来创建算数级数序列的通用函数&#xff0c;返回一个[start, start step, start 2 * step, ...]结构的整数序列&#xff1b;py2中的range()函数用法&#xff1a;&#xff08;推荐学习&#xff1a;Python视频教程&#xff09; range()返回的是一个列表 >&g…

mysql AUTO_INC 是否锁_AUTO-INC锁的一些思考

AUTO-INC锁是一个表级锁&#xff0c;这种锁是作用于语句的而不是事务(即语句执行完了锁就会被释放)。innodb_autoinc_lock_mode用于控制AUTO-INC的锁表逻辑&#xff0c;可能的取值为0,1,2.innodb_autoinc_lock_mode0 (每次都会产生表锁)不管是对于simple inserts(insert into v…

Java 8可选

在编程时&#xff0c;我们都面临着最&#xff08; 臭名昭著 &#xff09;的NullPointerException 。 而且我相信我们所有人都同意&#xff0c;遇到NullPointerException也是一种痛苦。 为了使读者了解最新情况&#xff0c;著名的计算机科学家Tony Hoare引入了空引用&#xff0c…

matlab cat函数_如何用Matlab编写贪吃蛇游戏?(持续更新)

今后我们实验室的研究重点将会聚焦在“基于游戏的测评”和”教育游戏化“这两个主题上&#xff0c;因此很有必要研究实现“爆款”游戏的一些基本的技术方法。这篇文章将介绍如何借助Matlab GUI 面向对象编程技术实现贪吃蛇游戏。所有的游戏都可以解构成至少两个层次&#xff1…

python程序设计案例课堂第二篇_Python程序设计案例课堂第二篇核心技术第十章图形用户界面...

第10章 图形用户界面保存并运行程序&#xff0c;结果如图10-1所示。C:\Users\Administrator>python d:\python\ch10\10.1.py图10-1 程序运行结果【案例剖析】上述代码的含义分析如下。(1) 第1行&#xff1a;加载tkinter 模块。(2) 第 2 行&#xff1a;使用tkinter 模块的Tk(…

fprintf函数的用法matlab_极力推荐这个Matlab教程

点击蓝字 关注我们儿童节快乐前些日子, 由于一些原因的需要, 又把曾经的毕业论文拿来, 改吧改吧, 发现有些地方真的惨目忍睹, 只怪当时太年轻, 没想到给自己挖了一个大坑, 不,, 应该称之为巨坑, 对于论文中涉及到的代码, 当时主要使用了伪代码的形式, 以及现学现用的Python, 可…

websockets_使用Java WebSockets,JSR 356和JSON映射到POJO的

websockets因此&#xff0c;我一直在研究Tyrus &#xff08;JSR 356 WebSocket for Java规范的参考实现&#xff09;。 因为我一直在寻找测试工具&#xff0c;所以我对在Java中同时运行客户端和服务器端感兴趣。 因此&#xff0c;恐怕此博客文章中没有HTML5。 在此示例中&…

查看mysql主从复制是否成功的命令_mysql主从复制 - hong查理的个人空间 - OSCHINA - 中文开源技术交流社区...

1.配置 my.cof服务器A(192.168.1.2)配置如下log-bin mysql-binserver-id 1expire-logs-days 7#日志设置最高7天replicate-do-db test #需要同步的binlog-ignore-db mysql #忽略同步的binlog-ignore-db information_schema #忽略同步的auto-increment-increment 2…

python抓取数据时失败_爬取数据缺失的补坑,Python数据爬取的坑坑洼洼如何铲平...

渣渣业余选手讲解&#xff0c;关于爬取数据缺失的补坑&#xff0c;一点点关于Python数据爬取的坑坑洼洼如何铲平&#xff0c;个人的一些心得体会&#xff0c;还有结合实例的数据缺失的补全&#xff0c;几点参考&#xff0c;仅供观赏&#xff0c;如有雷同&#xff0c;那肯定是我…

关于总决赛

可以将变量声明为final。 最终变量只能分配一次。 如果分配了最终变量&#xff0c;则将导致编译时错误&#xff0c;除非在分配前立即将其绝对取消分配。 分配任何最终变量后&#xff0c;将永远无法对其进行更改。 如果变量引用任何对象的任何实例&#xff0c;它将继续引用相同的…

java中void_关于java中void的用法?

阿波罗的战车void除了说明该方法没有返回值外&#xff0c;还有什么作用呢&#xff1f;构造方法同样也是没有返回值的&#xff0c;那它和void方法有什么区别呢&#xff1f;构造方法与方法又有什么区别&#xff1f;用具象的实物来表现的话三者有何种关系呢&#xff1f;id 除了说明…

卷积神经网络mnist手写数字识别代码_搭建经典LeNet5 CNN卷积神经网络对Mnist手写数字数据识别实例与注释讲解,准确率达到97%...

LeNet-5卷积神经网络是最经典的卷积网络之一&#xff0c;这篇文章就在LeNet-5的基础上加入了一些tensorflow的有趣函数&#xff0c;对LeNet-5做了改动&#xff0c;也是对一些tf函数的实例化笔记吧。环境 Pycharm2019Python3.7.6tensorflow 2.0 话不多说&#xff0c;先放完整源码…

glassfish_多种监视和管理GlassFish 3的方法

glassfishGlassFish 3支持多种监视和管理方法。 在本文中&#xff0c;我将简要介绍GlassFish提供的管理&#xff0c;监视和管理方法。 GlassFish管理控制台 GlassFish基于Web的管理控制台GUI可能是GlassFish管理最著名的界面。 默认情况下&#xff0c;运行GlassFish后&#xf…

java 阻塞锁_Java实现锁、公平锁、读写锁、信号量、阻塞队列、线程池等常用并发工具...

锁的实现锁的实现其实很简单&#xff0c;主要使用Java中synchronized关键字。public class Lock {private volatile boolean isLocked false;private Thread lockingThread null;public synchronized void lock() throws InterruptedExpection {while(isLocked){wait();}isLo…