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

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

ccwgpt 2024-10-13 01:38 26 浏览 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在或过头来仔细阅读并结合实际应用!原创不易,如果文章帮助了大家,欢迎转发!

相关推荐

RACI矩阵:项目管理中的角色与责任分配利器

作者:赵小燕RACI矩阵RACI矩阵是项目管理中的一种重要工具,旨在明确团队在各个任务中的角色和职责。通过将每个角色划分为负责人、最终责任人、咨询人和知情人四种类型,RACI矩阵确保每个人都清楚自己...

在弱矩阵组织中,如何做好项目管理工作?「慕哲制图」

慕哲出品必属精品系列在弱矩阵组织中,如何做好项目管理工作?【慕哲制图】-------------------------------慕哲制图系列0:一图掌握项目、项目集、项目组合、P2、商业分析和NP...

Scrum模式:每日站会(Daily Scrum)

定义每日站会(DailyScrum)是一个Scrum团队在进行Sprint期间的日常会议。这个会议的主要目的是为了应对Sprint计划中的不断变化,确保团队能够有效应对挑战并达成Sprint目标。为...

大家都在谈论的敏捷开发&amp;Scrum,到底是什么?

敏捷开发作为一种开发模式,近年来深受研发团队欢迎,与瀑布式开发相比,敏捷开发更轻量,灵活性更高,在当下多变环境下,越来越多团队选择敏捷开发。什么是敏捷?敏捷是一种在不确定和变化的环境中,通过创造和响应...

敏捷与Scrum是什么?(scrum敏捷开发是什么)

敏捷是一种思维模式和哲学,它描述了敏捷宣言中的一系列原则。另一方面,Scrum是一个框架,规定了实现这种思维方式的角色,事件,工件和规则/指南。换句话说,敏捷是思维方式,Scrum是规定实施敏捷哲学的...

敏捷项目管理与敏捷:Scrum流程图一览

敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示,以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例:这个流程图涵盖了Scrum框架的主要阶段和活动,其中包...

一张图掌握项目生命周期模型及Scrum框架

Mockito 的最佳实践(mock方法)

记得以前面试的时候,面试官问我,平常开发过程中自己会不会测试?我回答当然会呀,自己写的代码怎么不测呢。现在想想我好像误会他的意思了,他应该是想问我关于单元测试,集成测试以及背后相关的知识,然而当时说到...

EffectiveJava-5-枚举和注解(java枚举的作用与好处)

用enum代替int常量1.int枚举:引入枚举前,一般是声明一组具名的int常量,每个常量代表一个类型成员,这种方法叫做int枚举模式。int枚举模式是类型不安全的,例如下面两组常量:性别和动物种...

Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!

Maven简介Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。Maven是一个跨平台的项目管理工具。主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。仔...

Java单元测试框架PowerMock学习(java单元测试是什么意思)

前言高德的技术大佬在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。”这句话让我感触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现...

Spring框架基础知识-第六节内容(Spring高级话题)

Spring高级话题SpringAware基本概念Spring的依赖注入的最大亮点是你所有的Bean对Spring容器的存在是没有意识的。但是在实际的项目中,你的Bean必须要意识到Spring容器...

Java单元测试浅析(JUnit+Mockito)

作者:京东物流秦彪1.什么是单元测试(1)单元测试环节:测试过程按照阶段划分分为:单元测试、集成测试、系统测试、验收测试等。相关含义如下:1)单元测试:针对计算机程序模块进行输出正确性检验工作...

揭秘Java代码背后的质检双侠:JUnit与Mockito!

你有没有发现,现在我们用的手机App、逛的网站,甚至各种智能设备,功能越来越复杂,但用起来却越来越顺畅,很少遇到那种崩溃、卡顿的闹心事儿?这背后可不是程序员一拍脑袋写完代码就完事儿了!他们需要一套严谨...

单元测试框架哪家强?Junit来帮忙!

大家好,在前面的文章中,给大家介绍了以注解和XML的方式分别实现IOC和依赖注入。并且我们定义了一个测试类,通过测试类来获取到了容器中的Bean,具体的测试类定义如下:@Testpublicvoid...

取消回复欢迎 发表评论: