百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

从0到1上手JUnit5(junit5教程)

ccwgpt 2024-10-13 01:38 22 浏览 0 评论

本文假定读者有单元测试基础,不会对单元测试的概念做过多的介绍,主要讲解junit5的新功能用法,让读者快速上手Junit5。?

如果你想了解单元测试的基础概念可以阅读文章:一文搞定单元测试核心概念

注意:建议大家使用文章中推荐的jdk、Eclipse、mvn以及 pom.xml进行配置,可以确保大家代码的顺利运行!

JUnit5 框架构成

Junit5需要Java 8或更高版本,和 Junit4 只是一个单独的 Jar 包不同,目前的 Junit5 组成如下:

JUnit 5= JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Platform是 Junit 向测试平台演进,提供平台功能的模块,通过 JUnit Platform,其他的自动化测试引擎或开发人员自己定制的引擎都可以接入Junit 实现对接和执行

JUnit Jupiter, 这是 Junit5 的核心,可以看作是承载 Junit4 原有功能的演进,它包含了很多丰富的新特性来使 JUnit 自动化测试更加方便、功能更加丰富和强大。本系列就会重点围绕 Jupiter 中的一些特性进行介绍。Jupiter 本身也是一个基于 Junit Platform 的引擎实现。

JUnit Vintage,Junit发展了10数年,Junit 3 和 Junit 4 都积累了大量的用户,作为新一代框架,这个模块是对 JUnit3,JUnit4 版本兼容的测试引擎,使旧版本 junit 的自动化测试脚本也可以顺畅运行在 Junit5 下,它也可以看作是基于Junit Platform 实现的引擎范例。

Eclipse环境搭建

Eclipse从Oxygen.1a(4.7.1a) 开始支持Junit5

在Eclipse的 Marketplace中搜索Junit5,然后安全JUnit-Tools 如下图所示:

安装插件后,会在eclipse中自动装入junit5 Library,如下图:

Maven,强烈推荐如下配置!

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>

<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>

<junit.jupiter.version>5.5.2</junit.jupiter.version>

<junit.platform.version>1.5.2</junit.platform.version>

</properties>

<dependencies>

<dependency>

<groupId>org.junit.jupiter</groupId>

<artifactId>junit-jupiter-engine</artifactId>

<version>${junit.jupiter.version}</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.junit.platform</groupId>

<artifactId>junit-platform-runner</artifactId>

<version>${junit.platform.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.8.1</version>

</plugin>

<plugin>

<artifactId>maven-surefire-plugin</artifactId>

<version>2.22.2</version>

</plugin>

</plugins>

</build>

新增的断言

assertAll:用来校验所有断言是否为真。如下代码会导致校验失败

assertAll("person",

() ->assertEquals("John","John"),

() ->assertEquals("Doe","kevin")

);

assertTimeout:断言在超出给定超时之前,所提供的可执行代码块的执行完成。

assertTimeout(ofSeconds(1),() -> {

// Simulate task that takes morethan 10ms.

Thread.sleep(2000);

});

四个变化的注解

@BeforeAll 只执行一次,执行时机是在所有测试和@BeforeEach 注解方法之前。

@BeforeEach 在每个测试执行之前执行。

@AfterEach 在每个测试执行之后执行。

@AfterAll 只执行一次,执行时机是在所有测试和 @AfterEach 注解方法之后。

新增的实用标签,在指定条件下运行用例

新增Enabled相关标签,表示在指定系统、指定jdk版本等等条件下运行。详情如下:

用例只在指定系统中运行

@EnabledOnOs({ LINUX, MAC })

用例只在指定JDK版本时运行

@EnabledOnJre(JAVA_8)

用例只能在64位操作系统上执行的测试

@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")

需要传入环境变量DEBUG=true才能执行的测试@EnabledIfEnvironmentVariable(named = "DEBUG", matches = "true")

用例显示自定义名称

@DisplayName("测试用例1")

例如设置

@Test

@DisplayName("测试用例1")

void succeedingTest() {

assertAll("person",

() ->assertEquals("John","John"),

() ->assertEquals("Doe","kevin")

);

}

在执行结果中显示


用例无效

@Disabled

重复执行用例

@RepeatedTest(10)

用例超时

@Timeout(5)

嵌套

@Nested设计目的就是在测试类中嵌套其他测试类用以表明用例组之间的关系,个人感觉应用场景有限。

例如:

class NestedDemo {

@Test

void case1() {

assertTrue(true);

}

@Nested

class NewTest {

@Test

void caseN1() {

assertTrue(true);

}

@Test

void caseN2() {

assertTrue(false);

}

@Test

void caseN3() {

assertTrue(true);}


}

}

运行时会让你选择执行哪个测试类

参数化

@ParameterizedTest

@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba"})

void palindromes(Stringcandidate) {

assertTrue(StringUtils.isPalindrome(candidate));

}


@ParameterizedTest

@CsvSource({

"apple, 1",

"banana, 2",

"'lemon, lime', 0xF1"

})

void testWithCsvSource(String fruit, intrank) {

assertNotNull(fruit);

assertNotEquals(0, rank);

}

@ValueSource:声明一个基本类型的数组(String、int、long、double等),并且为测试方法提供调用参数,每个参数执行一次测试方法。

@EnumSource:为测试方法提供Enum常量参数,这个注释提供一个可选的name参数,通过其指定使用那些常量,如:names = {"DAY", "HOURS"}。还有一个可选的mode参数,能够通过names中声明的常量列表或者正则表达式来细粒度地控制那些常量将会被传递到测试方法中。

@MethodSource:可是通过这个注释引用测试类中的一个或者多个工厂方法,这些方法必须返回一个Stream、Interable、Iterator或者数组参数,工厂方法不能接收任何参数。默认情况下必须是static方法,除非声明了@TestInstace(Lifecycle.PER_CLASS)。如果测试方法中有多个参数,则需要返回一个Arguments实例的集合。

@CsvSource:在参数化测试方法中,通过参数列表声明参数,每组参数的不同值用逗号隔开。

@CsvFileSource:使用类路径中的CSV文件作为参数,每一行数据都会触发参数化测试的一次调用。

@ArgumentsSource:指定一个实现ArgumentsProvider接口的参数提供类作为参数化测试方法的参数提供者,这个类的provideArguments方法返回的Stream作为参数流。

用例执行顺序

import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;

import org.junit.jupiter.api.Order;

import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(OrderAnnotation.class)

class OrderedTestsDemo{

@Test

@Order(1)

void nullValues() {

// perform assertions against null values

}

@Test

@Order(2)

void emptyValues() {

// perform assertions against empty values

}

@Test

@Order(3)

void validValues() {

// perform assertions against valid values

}

}

自定义标签的使用

标签生成

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import org.junit.jupiter.api.Tag;

import org.junit.jupiter.api.Test;

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

@Tag("smoke")

@Test

public @interface Smoke{}

用例中使用标签

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.my.demo.Smoke;

public class TestTagDemo {

@Test

@Smoke

public void case1() {

System.out.println("case1");

assertTrue(true);

}

@Test

@Smoke

public void case2() {

System.out.println("case2");

assertTrue(false);

}

@Test

public void case3() {

System.out.println("case3");

assertTrue(false);

}

}

运行带标签的用例

Run As>Run Configuration

运行结果

如上图所示,只运行了@Somke标签的用例

maven-surefire-plugin中运行

在pom.xml文件中配置

<plugins>

<plugin>

<artifactId>maven-surefire-plugin</artifactId>

<version>3.0.0-M4</version>

<configuration>

<groups>smoke</groups>

</configuration>

</plugin>

注意,想要通过maven构建的时候执行用例,用例命名必须遵循如下格式:

**/Test*.java

**/*Test.java

**/*Tests.java

**/*TestCase.java

Suite

在JUnit 5 中使用@RunWith,@SelectPackages和@SelectClasses作为suite的常用方法。还可以配合@IncludeTags,执行需要具有某标签的用例。

代码如下所示:

@RunWith(JUnitPlatform.class)

@SelectClasses( ClassATest.class ) //执行某个类

@SelectPackages({"com.examples.packageA","com.examples.packageB"})

//执行某个包中的所有用例

public class JUnit5TestSuiteExample

{

}

注意:我在实际操作中发现在IDE中使用junit5,对其版本信息要求极高,强烈建议大家

使用如下配置(本机测试通过)

推荐jdk:1.8.0_151(1.8即可)

推荐Eclipse:Photon Release (4.8.0)

推荐mvn版本:3.6.3

推荐 pom配置

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>

<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>

<junit.jupiter.version>5.5.2</junit.jupiter.version>

<junit.platform.version>1.5.2</junit.platform.version>

</properties>

<dependencies>

<dependency>

<groupId>org.junit.jupiter</groupId>

<artifactId>junit-jupiter-engine</artifactId>

<version>${junit.jupiter.version}</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.junit.platform</groupId>

<artifactId>junit-platform-runner</artifactId>

<version>${junit.platform.version}</version>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.8.1</version>

</plugin>

<plugin>

<artifactId>maven-surefire-plugin</artifactId>

<version>2.22.2</version>

</plugin>

</plugins>

</build>

</project>

动态测试

注解@Test可以认为是静态测试方法,是在编译时指定的。在JUnit5中还有一类测试称为动态测试,可以在运行时改变。

@TestFactory:声明动态测试,声明的方法本身不是测试用例,而是生成测试用例的工厂方法。这个方法必须返回一个DynamicNode实例的Stream、Collection、Iterable或Iterator。DynamicNode有两个可实例化子类DynamicContainer和DynamicTest。动态测试的执行生命周期和@Test测试不同,同一个@TestFactory方法所生成的n个动态测试,@BeforeEach和@AfterEach只会在n个动态测试开始前和结束后执行一次,不会为每个单独的动态测试都执行。个人感觉应用场景有限,这里就不做详细介绍了。

总结

大家可以看到Junit5跟Junit4比有了很大的变化,个人认为其主要目的是对标TestNG,可以说Junit5跟TestNG更像了!?本文内容很多,建议大家只需要有个大概的印象即可,在实际工作中如果使用了Junit5在或过头来仔细阅读并结合实际应用!原创不易,如果文章帮助了大家,欢迎转发!

相关推荐

5 分钟搭建 Node.js 微服务原型(node 微服务架构)

微服务已成为在Node.js中构建可扩展且强大的云应用的主流方法。同时也存在一些门槛,其中一些难点需要你在以下方面做出决策:组织项目结构。将自定义服务连接到第三方服务(数据库,消息代理等)处理微服...

当前的前端,真的不配叫程序员吗?

今天看到一个比较令人震惊的帖子,说前端不配叫程序员,令我很吃鲸,是谁我就不说了,帖子出处是一个大龄程序员组里面的,想想也不觉得奇怪了,毕竟对于年龄比较大的程序员来说,前端起步比较晚,最开始就是一个切图...

聊聊asp.net中Web Api的使用(asp.net core web api教程)

扯淡随着app应用的崛起,后端服务开发的也越来越多,除了很多优秀的nodejs框架之外,微软当然也会在这个方面提供更便捷的开发方式。这是微软一贯的作风,如果从开发的便捷性来说的话微软是当之无愧的老大哥...

NodeJS中,listen Access:permission denied解决办法

错误描述:Win10系统,NodeJS程序。使用express框架开发的http服务器,启动时出现错误提示“listenAccess:permissiondenied"。错误原因:这是由于...

Hono — 下一代高性能web框架(天融信下一代vnp)

最近公司可能要有变革,要统计我们的技能。真的是很无语,但是有没有办法。哎,问豆包吧提起Hono大家可能很陌生,这是什么?但是我提到Expressjs、nodejs想必前端小伙伴很熟悉啊。那么Hon...

生活例子说明线程,简单明了(列举一个日常生活中的例子以程序的形式表示)

1.程序设计的目标在我看来单从程序的角度来看,一个好的程序的目标应该是性能与用户体验的平衡。当然一个程序是否能够满足用户的需求暂且不谈,这是业务层面的问题,我们仅仅讨论程序本身。围绕两点来展开,性能...

Node实战006:自定义模块的创建和使用详解

Node的应用是由模块组成的,每个文件的定义都是一个模块(module变量代表当前模块)并有自己的作用域。Node遵循commonjs的模块规范,用来隔离每个模块的作用域,使每一个模块在自身的命名空间...

Node.js基本内容和知识点(node.js的概念)

简单的说Node.js就是运行在服务端的JavaScript,起初段定位是后端开发语言,由于技术的不够成熟,一般小型项目会完全使用node.js作为后台支撑,大项目中,运行不够稳定,不会轻易使用...

干货 | 如何利用Node.js 构建分布式集群

引言在软件定义的世界里,企业通过Web应用和移动应用程序来提供大部分的服务,Node.js迅速成为时下最为流行的一个平台之一,就和它可以搭建响应速度快、易于扩展的web应用和移动应用有很大关系,并凭...

nodejs mongodb 实现简易留言板(node.js留言板)

一个朋友问了一下mongodb的一些操作问题我就做了下面这个简单的留言板给他做一个实例希望能帮助到他express的框架就不说了express的问题请移步nodejs之expressht...

nodejs mqtt 智能售货机系统物联网控制系统源码分享

智能售货机系统(Moleintelligentvendingmachinesystem)是一套物联网控制系统性的解决方案。主要涉及到的语言和库有c,c++,js,nodejs,vue.js,...

为什么 Node.js 这么火,而同样异步模式 Python 框架 Twisted 却十几年一直不温不火?

说nodejs只是靠营销的是否太天真了些?当初nodejs出来的时候各种BUG,我简单的测试其大文件传输都会出现各种问题。而同時期的其他阵营早就甩其几条街了。但是为什么却能一直不断发展壮大?...

2020年14个最有用的NodeJS库(node用什么数据库)

Express快速,简单,极简的节点Web框架对…有好处·易于处理多种类型的请求,例如GET,PUT,POST和DELETE请求·快速构建单页,多页和混合Web应用程序每周下载1100万Lice...

连载:2016年最好的JS框架和库(下)

继续上一期的介绍:Agility.jsAgility.js是专为JS服务的MVC库,你可以免费编写可再用和可维护的浏览器代码,Agility支持Js,样式(CSS)、内容(HTML)和行为(JS)。C...

awesome-nodejs 终极资源库:60K+星标的开发者宝藏

Node.js终极资源库:60K+星标的开发者宝藏引言在GitHub上,有一个备受瞩目的Node.js资源仓库,以其惊人的60.6k星标量和6kfork量,成为了Node.js开发者的必备参考。这个...

取消回复欢迎 发表评论: