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)
    @Test
    void test04() {
        System.out.println("这是第4个测试方法");
    }

    @Order(2)
    @Test
    void test01() {
        System.out.println("这是第1个测试方法");
    }

    @Order(3)
    @Test
    void test03() {
        System.out.println("这是第3个测试方法");
    }

    @Order(4)
    @Test
    void 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 {
    @Test
    void test1() {
        System.out.println("1");
    }
    ...
}

public class TestClass2 {
    @Test
    void 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

递归【2】(组合回溯(生成括号)、子集回溯(背包问题))

括号对 &#xff08;组合型回溯&#xff09; 分解成子问题&#xff0c;每一次添加括号分两步&#xff1a; if左括号小于n&#xff0c;加左括号&#xff0c;然后k(index1), if左括号大于有括号&#xff0c;加右括号&#xff0c;k(index1),然后收尾括号单独考虑&#xff0c;到…

设计模式之过滤器模式FilterPattern(十)

一、过滤器模式 过滤器模式&#xff08;Filter Pattern&#xff09;或标准模式&#xff08;Criteria Pattern&#xff09;是一种设计模式&#xff0c;这种模式允许开发人员使用不同的标准来过滤一组对象&#xff0c;通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模…

linux centos redis-6.2.6一键安装及配置密码

linux centos redis-6.2.6一键安装及配置密码 redis基本原理一、操作阶段&#xff0c;开始安装 redis基本原理 redis作为非关系型nosql数据库&#xff0c;一般公司会作为缓存层&#xff0c;存储唯一会话id&#xff0c;以及请求削峰作用 一、数据结构 Redis支持多种数据结构&a…

拯救者Legion Y9000X IRX9 2024(83FD)原装出厂Windows11系统镜像下载

lenovo联想2024款拯救者Y9000X IRX9 笔记本电脑【83FD】OEM预装Win11系统安装包&#xff0c;恢复开箱状态&#xff0c;自带恢复重置还原功能 链接&#xff1a;https://pan.baidu.com/s/1i_sVcnXF4qgsuj02rebe-Q?pwdyefp 提取码&#xff1a;yefp 联想原装WIN11系统自带所有…

Sentinel不使用控制台基于注解限流,热点参数限流

目录 一、maven依赖 二、控制台 三、基于注解限流 四、热点参数限流 五、使用JMeter验证 一、maven依赖 需要注意&#xff0c;使用的版本需要和你的SpringBoot版本匹配&#xff01;&#xff01; Spring-Cloud直接添加如下依赖即可&#xff0c;baba已经帮你指定好版本了。…

Android限制参数传递之StringDef注解的使用

文章目录 1. 引言2. 注解 StringDef2.1 举例2.2 StringDef源码解释 3. 其他类似注解 IntDef、LongDef4. 总结 1. 引言 在参数传递时&#xff0c;如果你想限制传入的参数只能是特定的几个值&#xff0c;该怎么做呢&#xff1f; 除了把参数类型定义为枚举值&#xff0c;还可以使…

0603作业

/* * function: 直接插入排序* param [ in] * param [out] * return */ void insert_sort_linklist(linklist* head,datatype data){linklist* phead;while(NULL!p->pnext && p->pnext->param …

【学永远不嫌晚】Linux操作系统,linux教程,动力节点linux,老杜linux

碎碎念 总是遇到一些恶心的事情 看最新教程 老师安装的是 vm17 pro&#xff0c;想着也去安装&#xff0c;搜了一大堆&#xff0c;都指向官网下载。 https://support.broadcom.com/group/ecx/productdownloads?subfamilyVMwareWorkstationPro 安装显示没有 entitlement&#…

SpringCloud 服务调用 spring-cloud-starter-openfeign

spring-cloud-starter-openfeign 是 Spring Cloud 中的一个组件&#xff0c;用于在微服务架构中声明式地调用其他服务。它基于 Netflix 的 Feign 客户端进行了封装和增强&#xff0c;使其与 Spring Cloud 生态更好地集成。 1. Feign Feign 是一个声明式的 Web Service 客户端…

【Python】一文向您详细介绍 `__dict__` 的作用和用法

【Python】一文向您详细介绍 __dict__ 的作用和用法 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕…

网络安全形势与WAF技术分享

我一个朋友的网站&#xff0c;5月份时候被攻击了&#xff0c;然后他找我帮忙看看&#xff0c;我看他的网站、网上查资料&#xff0c;不看不知道&#xff0c;一看吓一跳&#xff0c;最近几年这网络安全形势真是不容乐观&#xff0c;在网上查了一下资料&#xff0c;1、中国信息通…

Wow Tab插件,一款能让你的Edge浏览器开挂的插件,微软官方出品

首先问你个问题&#xff0c;你的浏览器起始页是什么样的界面&#xff1f;是默认的界面还是极简的界面&#xff1f;又或者是既简洁又功能丰富的新型起始页呢&#xff1f;如果你的起始页是浏览器默认的&#xff0c;从来都没有更改过的话&#xff0c;建议你可以尝试一些第三方的起…

QT C++(QT控件 QPushButton,QRadioButton,QCheckBox)

文章目录 1. QPushButton 普通按钮2. QRadioButton 单选按钮3. QCheckBox 复选按钮 1. QPushButton 普通按钮 QPushButton中的重要属性 text&#xff1a;按钮中的文本icon&#xff1a;按钮的图标iconSize&#xff1a;按钮中图标的尺寸shortCut&#xff1a;按钮对应的快捷键&a…

vs2013 - 打包

文章目录 vs2013 - 打包概述installshield2013limitededitionMicrosoft Visual Studio 2013 Installer Projects选择哪种来打包? 笔记VS2013打包和VS2019打包的区别打包工程选择view打包工程中单击工程名称节点&#xff0c;就可以在属性框中看到要改的属性(e.g. 默认是x86, 要…

LabVIEW控制PLC的实现方式

LabVIEW与PLC的结合可以充分发挥两者的优点&#xff0c;实现更高效、灵活和可靠的自动化控制系统。本文将详细介绍LabVIEW控制PLC的实现方式&#xff0c;包括通信接口、数据交换、编程方法及实际应用案例&#xff0c;帮助用户理解并应用这一技术。 通信接口 常见通信协议 La…

【SQLAlChemy】常见的数据类型有哪些,Column可选的参数有哪些呢?

常见数据类型与Column参数 常见类型 Integer&#xff1a;整数类型&#xff0c;对应数据库的 int 类型。Float&#xff1a;浮点数类型&#xff0c;对应数据库的 float 类型。它占用 32 位空间。Double&#xff1a;双精度浮点数类型&#xff0c;对应数据库的 double 类型&#…

【GD32F303红枫派使用手册】第十一节 ADC-电源电压单通道ADC检测实验

11.1 实验内容 通过本实验主要学习以下内容&#xff1a; ADC的简介 GD32F303 ADC工作原理 查询方式实现ADC单通道采样 11.2 实验原理 11.2.1 ADC原理 我们知道&#xff0c;自然界中有非常多的模拟信号&#xff0c;比如上一节提到的光照强度&#xff0c;还有其他的例如温…

Python教程:Python操作MySQL基础使用

8、Python操作MySQL基础使用 8.1 安装pymysql pip install pymysql8.2 测试连接 测试代码 from pymysql import Connection# 获取到MySQL数据库的链接对象 conn Connection(# 主机名hostlocalhost,# 端口号,默认3306port3306,# 账户名userroot,# 密码password3535 )# 打印…

【JavaEE】Spring Boot 配置文件详解

一.配置文件的相关概念. 配置文件主要用于配置应用程序的行为和属性. Spring Boot的配置文件提供了一种灵活且强大的方式&#xff0c;用于管理应用程序的配置信息。很多项目或框架的配置信息也放在配置文件中: 项目的启动端口.数据库的连接信息(用户名/密码/驱动等的信息).第三…

Python 使用scrapy框架

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