Junit 单元测试 详解,包你掌握

Java单元测试----Junit详解

1 什么是 Junit

JUnit 是一个广泛使用的 Java 单元测试框架。它用于编写和运行可重复的测试,以验证 Java 程序的行为是否符合预期

也许有人会好奇,之前学的 Selenium 和 Junit 有什么关系?答案就是没关系!

这里,我们使用的是 Junit5

2 前期准备

在Java中,对于一个普通的maven项目,我们要使用 Junit 是需要先导入相应的依赖的。(SpringBoot 项目集成了,不需要额外导入依赖)。

下面是需要导入的依赖:

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.9.1</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.9.1</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite --><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.9.1</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>5.9.1</version><scope>test</scope></dependency>

下面是这些依赖的作用:如果不理解的话,可以先看下面的核心功能,有了这些依赖,才能使用下面的功能

image-20240608173045594

3 核心功能

3.1 常用的注解

注解:用于标识和管理测试方法和生命周期方法。

  • @Test:标识一个测试方法。
  • @BeforeEach@AfterEach:在每个测试方法之前和之后运行的方法。
  • @BeforeAll@AfterAll:在所有测试方法之前和之后运行的方法,通常用于静态方法。

下面分别来看一下这些注解:

@Test

@Test 用来表示当前的方法是一个测试方法,在 Junit 中,我们可以单独执行这个方法

image-20240608174238474

我们只运行第一个,就会得到下面的效果:

image-20240608174310043

如果点击类名旁边的那个绿三角,则会都运行:

image-20240608174336347

说明@Test 注解的方法不需要是 public 的,但必须是无参数的


@BeforeEach @AfterEach

@BeforeEach

  • 功能:在每个测试方法之前运行的方法。
  • 使用场景:用于在每个测试方法执行之前设置测试环境,如初始化变量或对象

@AfterEach

  • 功能:在每个测试方法之后运行的方法。
  • 使用场景:用于在每个测试方法执行之后清理测试环境,如释放资源或重置变量。

下面看一个简答的例子:

image-20240608175811706

运行效果:

image-20240608175902566


@BeforeAll @AfterAll

@BeforeAll

  • 功能:在所有测试方法之前运行的方法,通常只运行一次。
  • 使用场景:用于执行一次性的全局初始化,如设置静态资源或配置共享的状态。

@AfterAll

  • 功能:在所有测试方法之后运行的方法,通常只运行一次。
  • 使用场景:用于执行一次性的全局清理,如关闭静态资源或释放共享的状态。

说明

  • 其修饰方法必须是 static 的。(这篇文章中 点击跳转 讲解了为什么必须被 static 修饰)
  • 只会运行一次,无论有多少个测试方法。

简单的例子:在刚才代码的基础上加上这两句

image-20240608181126491

运行效果:

image-20240608181054377


3.2 测试用例的执行顺序

测试用例的执行顺序是什么呢?会不会有人刚开始跟我一样,认为是按照顺序执行的呢?下面咱们来看一下:

@Test
void test04() {System.out.println("这是第四个测试方法");
}@Test
void test01() {System.out.println("这是第一个测试方法");
}@Test
void test03() {System.out.println("这是第三个测试方法");
}@Test
void test02() {System.out.println("这是第二个测试方法");
}

这是四个测试方法,如果按照顺序执行,那么应该是: 4132,下面来看一下,是不是这样呢?

image-20240608181829327

结果发现,根本不是我们想的那样,怎么才能让他按照我们设置的顺序来直接呢?我们可以 指定顺序

指定顺序

JUnit 5 引入了 @TestMethodOrder 注解,用于指定测试方法的执行顺序。可以通过以下几种方式来控制顺序:

  • OrderAnnotation:按 @Order 注解的值来执行。
  • MethodName:按方法名的字典顺序来执行。
  • Alphanumeric:按字母和数字顺序来执行。
  • Custom:自定义顺序,通过实现 MethodOrderer 接口来定义

在日常使用中,我们多用第一个,下面对第一个举例:

需要现在类前加入注解:@TestMethodOrder(MethodOrderer.OrderAnnotation.class)

然后在每个测试方法前加上 @Order(数字),最后的执行顺序就按照 @Order 注解的值来执行

这次,执行顺序应该就和我们刚刚想的一样,是 4132

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JunitTest3 {@Order(1)@Testvoid test04() {System.out.println("这是第4个测试方法");}@Order(2)@Testvoid test01() {System.out.println("这是第1个测试方法");}@Order(3)@Testvoid test03() {System.out.println("这是第3个测试方法");}@Order(4)@Testvoid test02() {System.out.println("这是第2个测试方法");}
}

image-20240608183216038


3.3 参数化

参数化就是测试方法里有参数,上面写到,使用 @Test 时,方法必须是无参的,所以,使用参数化的方法时,就不能使用 @Test 了,不然会报错。

单参数

使用 @ParameterizedTest @ValueSource()

@ParameterizedTest 标识一个参数化测试方法

@ValueSource() 是用来传参的,支持的值类型包括:short、byte、int、long、float、double、char、boolean 和 String。

示例

以下是一个使用 @ParameterizedTest@ValueSource 的简单示例:

@ParameterizedTest
@ValueSource(ints = {1, 2, 3, 4}) // @ValueSource(ints = 1)
void Test03(int x) {System.out.println("接收的参数是x = " + x);
}

image-20240608190001936

@ParameterizedTest:标识 Test03 方法是一个参数化测试。

@ValueSource(ints = {1, 2, 3, 4}):提供一组整型参数。这个测试方法将使用这些参数分别运行四次,每次传入一个数值。

也可以只传入一个 @ValueSource(ints = 1),这样就只会输出:接收的参数是x = 1

@ValueSource 的其他类型

@ValueSource 可以用来提供不同类型的简单值。以下是一些例子:

  • 整数类型

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5})
    void testWithIntValues(int number) {......
    }
    
  • 字符类型

    @ParameterizedTest
    @ValueSource(chars = {'A', 'B', 'C'})
    void testWithCharValues(char ch) {......
    }
    
  • 布尔类型

    @ParameterizedTest
    @ValueSource(booleans = {true, false})
    void testWithBooleanValues(boolean value) {......
    }
    

也就是基本类型加个s,

shorts:用于短整型数组 (short)

bytes:用于字节数组 (byte)

ints:用于整型数组 (int)

longs:用于长整型数组 (long)

floats:用于浮点型数组 (float)

doubles:用于双精度浮点型数组 (double)

chars:用于字符数组 (char)

booleans:用于布尔型数组 (boolean)

strings:用于字符串数组 (String)


多参数

使用 @ParameterizedTest @CsvSource()

例子:

单个参数
@ParameterizedTest
@CsvSource({"apple", "banana","cherry"})void test(String fruit) {System.out.println(fruit);
}

image-20240608191737515

多个参数
@ParameterizedTest
@CsvSource({"apple, 1", "banana, 2", "cherry, 3"})void test(String fruit, int rank) {System.out.println(fruit + rank);
}

image-20240608192019027

含有特殊字符和引号

当 CSV 中包含特殊字符或逗号时,可以使用引号将其括起来:

@ParameterizedTest
@CsvSource({"'apple, green', 1", "'banana, yellow', 2", "'cherry, red', 3"})void test(String fruit, int rank) {System.out.println(fruit + " " + rank);
}

image-20240608192201215

使用文件传递参数

当参数较多的时候,还可以通过文件来传递参数

@CsvFileSource(resources = "文件名.csv") // 注意:文件必须是.csv类型

例子:

@ParameterizedTest
@CsvFileSource(resources = "test01.csv")void Test05(String name, int age) {System.out.println("name:" + name + ", age:" + age);
}

test01.csv 文件的内容:使用逗号分隔

image-20240608192821708

结果:

image-20240608192848989

通过方法生成参数

@MethodSource("方法名")

@ParameterizedTest
@MethodSource("Generate")void Test06(String name, int age) {System.out.println("姓名:" + name + "年龄:" + age);
}// 这个方法用来创建参数
public static Stream<Arguments> Generate() {return Stream.of(Arguments.arguments("张三", 13),Arguments.arguments("李四",14));
}

image-20240608193108287

3.4 测试套件

在 JUnit 中,测试套件(Test Suite)用于将多个测试类捆绑在一起,以便于一次性运行。

JUnit 5 中的测试套件

在 JUnit 5 中,测试套件通过 @Suite@SelectPackages@SelectClasses 注解来定义。以下是创建一个测试套件的步骤和示例:

1. 创建测试类

首先,创建一些测试类(与上面相同):

public class TestClass1 {@Testvoid test1() {System.out.println("1");}...
}public class TestClass2 {@Testvoid test2() {System.out.println("2");}...
}
2. 创建测试套件类

然后,创建一个测试套件类,将这些测试类包含在一起:

通过class运行测试用例

@Suite
@SelectClasses({ TestClass1.class, TestClass2.class })
public class TestSuite {// 这个类保持为空,它的目的是作为持有注解的入口
}

这段代码将执行 TestClass1 和 TestClass1这两个类中的全部测试用例

按包选择测试类:

@Suite
@SelectPackages(value = {"example", "example2")
public class TestSuite {// 这个类保持为空,它的目的是作为持有注解的入口
}

在这个示例中,将执行 example 和 example2 这两个包中的全部测试用例


3.5 断言

在软件测试中,断言(assertion)是用于验证程序行为是否符合预期的重要工具。断言方法用于验证测试中期望的结果与实际结果是否一致,如果不一致,测试将失败并报告错误。这样,就不用我们自己写 if 等来判断了。

在 Junit 中 使用 Assertions 这个类来调用他的方法

一些常见的方法:

assertEquals(expected, actual):验证两个值是否相等。

assertNotEquals(unexpected, actual):验证两个值是否不相等。

assertTrue(condition):验证条件是否为真。

assertFalse(condition):验证条件是否为假。

assertNull(object):验证对象是否为空。

assertNotNull(object):验证对象不为空。

assertThrows(expectedType, executable):验证代码抛出了预期的异常。

assertTimeout(Duration, executable):验证代码在规定时间内执行完毕。

image-20240608205656164

下面来看一个简单的例子:

@Test
void test07() {int x = 10;int y = 20;Assertions.assertEquals(x,y);String temp = null;Assertions.assertNull(temp);
}

image-20240608205936557

如果出错,后面的也不会执行

还可以点击 Click to see difference 来查看预期结果和真实结果之间的差异

image-20240608210123698

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

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

相关文章

debian12安装时分区方案

一、初次尝试 一共设置了4个分区&#xff0c;其中根目录/分区46G&#xff0c;swap分区10G&#xff08;电脑内存为6G&#xff09;&#xff0c;/boot分区200M&#xff0c;/home分区55G。系统安装之后的实际占有情况为&#xff1a; 二、调整后情况 一共设置了4个分区&#xff0c…

基于Simulink的双端行波测距

1 输电线路故障仿真模型 基于双端行波测距理论&#xff0c;在MATLAB软件中搭建的三相50Hz的输电线路故障仿真模型如图1所示&#xff0c;该模型包含了三相电源、输电线路、故障发生器和示波器模块等。主要仿真参数设置如下:仿真时间为 0~0.1s,采用固定步长 10-7和ode3 算法&…

【手推公式】如何求SDE的解(附录B)

【手推公式】如何求SDE的解&#xff08;附录B&#xff09; 核心思路&#xff1a;不直接求VE和VP的SDE的解xt&#xff0c;而是求xt的期望和方差&#xff0c;从而写出x0到xt的条件分布形式&#xff08;附录B&#xff09; 论文&#xff1a;Score-Based Generative Modeling throug…

LangChain4j实战

基础 LangChain4j模型适配: Provider Native Image Sync Completion Streaming Completion Embedding Image Generation Scoring Function Calling OpenAI ✅ ✅ ✅ ✅ ✅ ✅ Azure OpenAI ✅ ✅ ✅ ✅ ✅ Hugging Face ✅ ✅ Amazon Bedrock ✅ ✅…

Functional ALV系列 (09) - 双击跳转到另外一个ALV

在查看数据的时候&#xff0c;不总是只有一个界面&#xff0c;为了让用户更方便地查看数据&#xff0c;需要根据当前的数据跳转到另外的界面中&#xff0c;比如查看明细等。本文演示 ALV 比较实用的功能&#xff1a;双击 ALV 单元格跳转到另外一个 ALV 中。 要实现的业务场景&…

CTFHUB-技能树-web-信息泄露

目录 1.目录遍历 2.PHPINFO 3.备份文件下载 3.1 网站源码 3.2 bak文件 3.3 vim缓存 3.4 .DS_Store 4.Git泄露 4.1 Log 4.2 Stash 4.3 Index 5.SVN泄露 6.HG泄露 1.目录遍历 这个没什么好讲的&#xff0c;进去直接点击找flag,然后在下面目录翻&#xff0c;就找到了 …

晶振十大品牌

晶振是电路的心脏&#xff0c;特别对抖动、稳定度有要求&#xff0c;当然除了稳定度&#xff0c;抖动&#xff0c;还对环境温度有要求&#xff0c;优秀的厂商如下&#xff1a; 链接&#xff1a; 晶振十大品牌-晶振品牌-振荡器品牌-Maigoo品牌榜

最新下载:PDFFactoryFinePrint【软件附加安装教程】

简介&#xff1a; pdfFactory是一款无须 Acrobat 创建 Adobe pdf 文件的打印机驱动程序&#xff0c; 提供的创建 PDF 文件的方法比其他方法更方便和高效。 pdfFactory 支持从所有应用程序轻松、可靠地创建 PDF 文件。 支持将单页或两页的文档&#xff0c;直接打印为PDF文件&a…

VSFT匿名用户访问-设置

1、先备份配置档 cp -av /etc/vsftpd/vsftpd.conf{,_bak} 2、编辑配置档&#xff0c;修改以下参数 vim /etc/vsftpd/ vsftpd.conf anonymous_enableYES -----允许匿名用户访问 anon_upload_enableYES -----允许匿名用户上传 anon_mkdir_write_enableYES …

电子电气架构 ---车载安全防火墙

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

后台管理系统排序混乱,分页出现重复条例

检查了接口和请求参数都没有问题。 查询数据库发现是排序字段create_time 都相同导致的。没有区分度。 解决方案 按照唯一id排序 避免create_time 大批量相同 order by create_time &#xff0c;xxx 两个排序字段

搭建自己的组件库<2>dialog 组件

目录 设置title 插槽显示 控制宽高 关闭对话框 transition实现动画 引入深度选择器 同样创建组件dialogue.vue后全局注册 dialogue模版&#xff1a; <template><!-- 对话框的遮罩 --><div class"miao-dialog_wrapper"><!-- 真的对话框 …

The 18th Northeast Collegiate Programming Contest(5/9/13)

心得 赛中ac&#xff1a;5&#xff0c;目前ac&#xff1a;9&#xff0c;题目总数&#xff1a;13 中档可做题还是很多的&#xff0c;可惜遇到了难绷的queueforces&#xff0c; 最后15min才判出来&#xff0c;oi赛制5wa4遗憾离场&#xff0c;赛后把几个题都给调过了&#xff0…

Macbook M芯片JDK的安装

Macbook M芯片JDK的安装 下载 搜索zulu&#xff1b; 进入这个网址 https://www.azul.com/downloads/#zulu 进入页面后向下滑动 选择对应选项 然后点击Download进行下载。 选择.dmg格式的安装包&#xff0c;点击。 安装 下载完成后&#xff0c;到下载目录&#xff0c;双击…

MSPM0l1306——配置滴答定时器

我们配置好了滴答定时器之后&#xff0c;还要手动编写滴答定时器的中断服务函数&#xff0c;因为我们开启的滴答定时器的中断&#xff0c;当滴答定时器的计数值从我们设置的值减到0时&#xff0c;就会触发一次中断&#xff0c;触发中断就会执行中断服务函数。各个中断的中断服务…

【Spring Boot】异常处理

异常处理 1.认识异常处理1.1 异常处理的必要性1.2 异常的分类1.3 如何处理异常1.3.1 捕获异常1.3.2 抛出异常1.3.4 自定义异常 1.4 Spring Boot 默认的异常处理 2.使用控制器通知3.自定义错误处理控制器3.1 自定义一个错误的处理控制器3.2 自定义业务异常类3.2.1 自定义异常类3…

树莓派 5 AI 套件(Hailo-8L)使用教程

系列文章目录 前言 The Raspberry Pi AI Kit Raspberry Pi AI 套件将 Raspberry Pi M.2 HAT 与 Hailo AI 加速模块捆绑在一起&#xff0c;供 Raspberry Pi 5 使用。套件包含以下内容&#xff1a; 包含神经处理单元&#xff08;NPU&#xff09;的 Hailo AI 模块Raspberry Pi M.…

STM32 proteus + STM32Cubemx仿真教程(第二课按键教程)

文章目录 前言一、STM32按键的原理二、STM32Cubemx创建工程三、proteus仿真电路图四、程序代码编写4.1函数介绍4.2使用按键点亮LED灯 总结 前言 本篇文章开始带大家学习如何使用proteus和STM32Cubemx来完成STM32的学习&#xff0c;第二节课我们先来学习按键的用法。 proteus使…

五款软件推荐:U盘数据不小心删除了?帮你快速找回!

U盘数据不小心删除了怎么恢复&#xff1f;U盘是一种便携式存储设备&#xff0c;因其小巧轻便而广受欢迎。但是&#xff0c;U盘也常常会遇到数据丢失的问题。当U盘数据丢失时&#xff0c;需要找到一款可靠的数据恢复软件来恢复数据。 接下来为大家推荐5款好用的免费U盘数据恢复软…

Python 使用scrapy框架

1、安装scrapy 2、使用scrapy创建项目,在终端命令行 执行如下命令&#xff0c;会创建一个myproject项目 scrapy startproject myproject 3、创建完成后&#xff0c;目录结构如下 4、cd myproject进入项目 ,执行scrapy genspider weather ******&#xff0c;会在spiders下创建…