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

JUnit 5 –基础相关推荐

  1. JUnit 5 –架构

    现在我们知道如何设置JUnit 5并使用它编写一些测试 ,下面让我们看一下. 在本文中,我们将讨论JUnit 5架构以及采用这种方式的原因. 总览 这篇文章是有关JUnit 5的系列文章的一部分: 设 ...

  2. Android下使用JUnit

    Andorid下使用Junit 测试框架,是步入正规的Androdid开发的必经之路,在Junit 中可以得到组件,可以模拟发送事件,检测程序处理的正确性,下面就开始我们的教程: Java代码 工具: ...

  3. Android单元测试(一):JUnit框架的使用

    JUnit框架的使用 前言 工程介绍 JUnit介绍 什么是JUnit JUnit引入 JUnit注解 JUnit断言 JUnit使用 基础用法 参数化测试 assertThat用法 用法 自定义匹配 ...

  4. 用Junit写单元测试用例

    要使用JUnit框架,首先要引入import org.junit.*;其中包括大多数可能是用到的库函数 还有一个经常和junit一起使用的库函数,import org.junit.Assert.*; ...

  5. Maven运行JUnit测试(http://www.360doc.com/content/13/0927/15/7304817_317455642.shtml)

    Maven单元测试 分类: maven  2012-05-09 15:17  1986人阅读  评论(1)  收藏  举报 maven 测试 junit 单元测试 java random 目录(?)[ ...

  6. 《精通移动app测试实战:技术、工具和案例》图书目录

    图书相关链接: 京东网:http://item.jd.com/11891239.html 当当网:http://product.dangdang.com/23924601.html 亚马逊:https ...

  7. junit5和junit4_JUnit 5 –架构

    junit5和junit4 现在我们知道如何设置JUnit 5并使用它编写一些测试 ,下面让我们看一下. 在本文中,我们将讨论JUnit 5架构以及采用这种方式的原因. 总览 这篇文章是有关JUnit ...

  8. mockito_书评:Mockito Essentials

    mockito Sujoy Acharya的Mockito Essentials副标题( Packt出版 ,2014年10月)是:"实用指南,可帮助您使用Mockito进行单元测试并开始运行 ...

  9. 书评:Mockito Essentials

    Sujoy Acharya的Mockito Essentials副标题( Packt Publishing ,2014年10月)是:"实用指南,可帮助您使用Mockito进行单元测试并开始运 ...

最新文章

  1. mysql 常用sql与命令
  2. zg手册 之 python2.7.7源码分析(1)-- python中的对象
  3. STC89C52单片机 串口通信
  4. 第十届 蓝桥杯样题 —— 信用卡号验证
  5. Spring Web Flow 2.0 入门详解
  6. 在Linux系统里安装Virtual Box的详细步骤 1
  7. Mac AndroidStudio常用快捷键
  8. 经典面试题(30):以下代码将输出的结果是什么?
  9. shell监控web服务的多种方案
  10. 2017.4.16 级数求和 思考记录
  11. 风变python学习2---字符串,整数,浮点型数据分析,应用
  12. Android原生获取经纬度位置信息
  13. php后台登录页,后台登录页面模板源码
  14. PCB工程师级别评定标准
  15. Java:Java还很重要吗?
  16. 跨境人必收藏!掘金新赛道,带你科学开启TikTok Shop英国市场
  17. 一个初学者的留言板(登录和注册)
  18. hdu 多校赛 第二场
  19. 【Ansoft Maxwell】Unable to locate or start COM engine on ‘Loacal Machine‘解决方案
  20. 数值分析试题解析p172页 1/h[u(xi+1,tk)-u(xi-1,tk)]对应的截断误差是否答案给错了,应该是h^2/3而不是h^2/6

热门文章

  1. Spring MVC的GET与POST请求url-pattern坑
  2. Oracle入门(五A)之conn命令
  3. 教你如何监控 Java 线程池运行状态
  4. 如何用spring boot写一个注册页面
  5. 求 1-100 之间不能被 3 整除的数之和
  6. 使用java将字符串写入到指定的文件中
  7. 捕获异常VS抛出异常
  8. 云服务器mqtt协议,云服务器mqtt协议
  9. jsap支付_Java命令行界面(第20部分):JSAP
  10. 渴望 英语_渴望订阅– RxJava常见问题解答