Java测试框架——JUnit详解(45)

news2024/11/17 23:40:46

文章目录

  • 前言
  • 何为JUnit?
  • 官方资料
  • JUnit4
    • 常用注解和断言
    • 代码测试搭建一个JUnit测试环境
    • 生命周期
    • 忽略测试
    • 断言测试
    • 异常测试
    • 测试时间
    • 套件测试
  • JUnit5
    • JUnit5对比JUnit4的好处
    • 导包的改变
    • 注解的改变
    • 扩展JUnit
    • 新功能:
  • 参考文章

JUnit是Java编程语言的单元测试框架,用于编写和运行可重复的自动化测试,也是当下主流的Java测试框架


前言

如果有对单元测试还不熟悉的小伙伴可以看一下我的这篇文章——浅谈单元测试,本文我们主要针对JUnit 来讲解Java中的常用单元测试关于JUnit4和5的区别可以参考这篇文章,从JUnit 4迁移到JUnit 5:重要的区别和好处。

何为JUnit?

JUint是Java编程语言的单元测试框架,用于编写和运行可重复的自动化测试

JUnit的好处(来自百度百科):

  1. 简单易用:JUnit 的 API 非常简单,开发人员可以轻松地编写和执行单元测试。

  2. 可维护:单元测试是可重复执行的,因此在修改代码时,可以通过运行单元测试来确保修改后的代码不会破坏已有的功能。

  3. 可扩展:JUnit 提供了一些扩展点,使开发人员可以根据自己的需要扩展它。

  4. 可集成:JUnit 可以与大多数流行的 Java IDE 和构建工具集成,开发人员可以在开发过程中轻松地执行单元测试。

  5. 社区支持:JUnit 拥有庞大的用户群和开发团队,因此如果遇到问题,可以得到很好的帮助。

官方资料

学习一个东西,最好的办法就是去看官方文档:
在这里插入图片描述
junit4官网
junit5官网

下面我根据官网和自己常用测试,来讲解JUnit

JUnit4

常用注解和断言

在这里插入图片描述
在这里插入图片描述

代码测试搭建一个JUnit测试环境

这是一个springboot项目,为了后续的SpringBoot2+H2+Mockito测试,读者也可以做一个maven项目

项目搭建:
maven包引入

<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test</name>
    <description>test</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
    		
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

测试@Test
在这里插入图片描述

package com.example.test;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */

public class HelloWorldTest {
    @Test
    public void test(){
        assertEquals(4, 1 + 3);
    }
}

执行结果:
在这里插入图片描述
@Test注解在方法上标记方法为测试方法,以便构建工具和 IDE 能够识别并执行它们。JUnit 4 需要测试方法为public,这和Junit 5 有差别。

生命周期

@Before,@BeforeClass,@After,@AfterClass

在这里插入图片描述

package com.example.test;

import org.junit.*;
/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class LifeCycleTest {
    @BeforeClass
    public static void beforeClass() {
        System.out.println("in before class");
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("in after class");
    }

    @Before
    public void before() {
        System.out.println("in before");
    }

    @After
    public void after() {
        System.out.println("in after");
    }

    @Test
    public void testCase1() {
        System.out.println("in test case 1");
    }

    @Test
    public void testCase2() {
        System.out.println("in test case 2");
    }
}

在这里插入图片描述

忽略测试

package com.example.test;

import org.junit.Test;
import org.junit.Ignore;
/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class IgnoreTest {
    @Ignore
    @Test
    public void Ignore(){
        System.out.println("IgnoreTest...");
    }
}

在这里插入图片描述

断言测试

在这里插入图片描述
我们简单测试三个方法,后面的读者有兴趣可以自行测试,代码如下:

package com.example.test;

import org.junit.Assert;
import org.junit.Test;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class AssertionTest {
    @Test
    public void AssertionT(){
        Assert.assertEquals(1,1);
        Assert.assertTrue(true);
        Assert.assertFalse(false);
    }
}

在这里插入图片描述

异常测试

@Test注解还提供了追踪异常的选择,expected 参数和 @Test 注释一起使用。

@Test(expected):用来指示期望抛出的异常类型。

如果有读者不知道Java中异常的类型可以参考我之前写过的这篇文章:java处理异常这一篇就够了

package com.example.test;

import org.junit.Test;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class AbnormalTest {
    @Test(expected = NullPointerException.class)
    public void Abnomal(){
        int a = 0;
        System.out.println(1/a);
    }
}

在这里插入图片描述

测试时间

简单的来说,就是JUnit中提供了一个如果测试时间超时的时候,也默认是测试失败,这个时间我们可以自己指定,@Test(timeout)

package com.example.test;

import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class TimeTest {
    @Test(timeout = 1000)
    public void time() throws InterruptedException {
        //time为毫秒
        
        //暂停时间
        TimeUnit.SECONDS.sleep(5000);
        System.out.println("in timeout exception");
    }
}

在这里插入图片描述

套件测试

指捆绑了几个单元测试用例并运行起来,JUnit中,@RunWith和@Suite是用来运行套件测试的

package com.example.test.kit;

import org.junit.Test;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class Test1 {
    @Test
    public void printMessage(){
        System.out.println("Test1");
    }
}

package com.example.test.kit;

import org.junit.Test;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
public class Test2 {
    @Test
    public void printMessage(){
        System.out.println("Test2");
    }
}

package com.example.test.kit;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

/**
 * @Author 秋名山码神
 * @Date 2023/1/2
 * @Description
 */
@RunWith(Suite.class)
@Suite.SuiteClasses({

        //此处类的配置顺序会影响执行顺序

        Test1.class,
        Test2.class
})
public class Test {

}

在这里插入图片描述

JUnit5

熟悉JUnit4,转变到JUnit5是十分容易的,并且JUnit 5可以使用Vintage库运行JUnit 4测试,这意味着对于JUnit4的项目你可以不用迁移测试,从而继续使用JUnit4的测试代码。

JUnit5对比JUnit4的好处

  • JUnit 5利用了Java 8或更高版本的特性,例如lambda函数,使测试更强大,更容易维护。
  • JUnit 5为描述、组织和执行测试添加了一些非常有用的新功能。例如,测试得到了更好的显示名称,并且可以分层组织。
  • JUnit 5被组织成多个库,所以只将你需要的功能导入到你的项目中。通过Maven和Gradle等构建系统,包含合适的库很容易。
  • JUnit 5可以同时使用多个扩展,这是JUnit 4无法做到的(一次只能使用一个runner)。这意味着你可以轻松地将Spring扩展与其他扩展(如你自己的自定义扩展)结合起来。

JUnit4 转变到JUnit5

  1. 将你的库和构建系统从JUnit 4更新到JUnit 5。确保在你的测试运行时路径中包含 junit-vintage-engine 工件,以允许你现有的测试执行。
  2. 使用新的JUnit 5构造开始构建新的测试。
  3. (可选)将JUnit测试用例转换为JUnit 5的测试用例。

导包的改变

maven改变:

<!-- 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>
    <scope>test</scope>
</dependency>

JUnit 5 使用新的 org.junit.jupiter 包。例如,org.junit.junit.Test变成了org.junit.jupiter.api.Test。

注解的改变

在这里插入图片描述
首先我们发现名称进行了改变,@Before变成了@BeforeEach等等……

其中@Test还将不再支持参数,这意味这JUnit4中,@Test(expected = Exception.class),不再支持,替换为:

@Test(expected = Exception.class)
public void testThrowsException() throws Exception {
    // ...
    //4
}
@Test
void testThrowsException() throws Exception {
    Assertions.assertThrows(Exception.class, () -> {
        //...
        //5
    });
}

扩展JUnit

在JUnit5中提供了@ExtendWith 注解,是可重复的,例如在JUnit4中添加Spring框架构建测试:

@RunWith(SpringJUnit4ClassRunner.class)
public class MyControllerTest {
    // ...
}

而在JUnit5中:

@ExtendWith(SpringExtension.class)
class MyControllerTest {
    // ...
}

新功能:

显示名称。使用JUnit 5,你可以在类和方法中添加@DisplayName注释。这个名称在生成报告时使用,这使得描述测试的目的和追踪失败更容易,比如说:

@DisplayName("Test MyClass")
class MyClassTest {
    @Test
    @DisplayName("Verify MyClass.myMethod returns true")
    void testMyMethod() throws Exception {    
        // ...
    }
}

断言:
断言。JUnit 5引入了一些新的断言,比如以下这些:

assertIterableEquals()使用equals()对两个迭代项进行深度验证。
assertLinesMatch()验证两个字符串列表是否匹配;它接受期望参数中的正则表达式。
assertAll() 将多个断言分组在一起。附加的好处是所有的断言都会被执行,即使单个断言失败。
assertThrows()和 assertDoesNotThrow()取代了 @Test 注释中的预期属性。


嵌套测试。JUnit 4中的测试套件是很有用的,但JUnit 5中的嵌套测试更容易设置和维护,它们能更好地描述测试组之间的关系,比如说:

@DisplayName("Verify MyClass")
class MyClassTest {
    MyClass underTest;

    @Test
    @DisplayName("can be instantiated")
    public void testConstructor() throws Exception {    
        new MyClass();
    }
    @Nested
    @DisplayName("with initialization")
    class WithInitialization {
        @BeforeEach
        void setup() {
            underTest = new MyClass();
            underTest.init("foo");
        }

        @Test
        @DisplayName("myMethod returns true")
        void testMyMethod() {
            assertTrue(underTest.myMethod());
        }
    }
}

测试的参数化
测试参数化在JUnit 4中就已经存在,有内置的库如JUnit4Parameterized或第三方库如JUnitParams等。在JUnit 5中,参数化测试完全内置,并采用了JUnit4Parameterized和JUnitParams等一些最好的特性。例子:

@ParameterizedTest
@ValueSource(strings = {"foo", "bar"})
@NullAndEmptySource
void myParameterizedTest(String arg) {
    underTest.performAction(arg);
}

其格式看起来像JUnitParams,其中参数直接传递给测试方法。注意,要测试的值可以来自多个不同的来源。这里,我只用了一个参数,所以使用@ValueSource很方便。@EmptySource和@NullSource分别表示你要在要运行的值列表中添加一个空字符串和一个空值(如果你使用这两个值,你可以把它们组合在一起,如上所示)。还有其他多个值源,比如@EnumSource和@ArgumentsSource(一种自定义值提供者)。如果你需要一个以上的参数,也可以使用@MethodSource或@CsvSource。

在JUnit 5中添加的另一个测试类型是@RepeatedTest,在这里,一个测试被重复指定次数的测试。


最后还是建议大家参考一下:junit5官网

参考文章

网络:
https://blog.csdn.net/qq_34264849/article/details/88243278
https://zhuanlan.zhihu.com/p/144763642

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

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

相关文章

list的介绍及模拟实现

&#x1f308;感谢阅读East-sunrise学习分享——list的介绍及模拟实现 博主水平有限&#xff0c;如有差错&#xff0c;欢迎斧正&#x1f64f;感谢有你 码字不易&#xff0c;若有收获&#xff0c;期待你的点赞关注&#x1f499;我们一起进步 今天想分享介绍一下STL的容器之一lis…

openharmony GPIO 驱动开发

openharmony GPIO 驱动开发GPIO 基础知识GPIO 基础知识——概念GPIO 基础知识——IO 复用GPIO 基础知识——GPIO 分组和编号GPIO 基础知识——用户态测试HDF 框架下 GPIO 驱动HDF 框架下的 GPIO 驱动——案例描述(以 HI3516DV300 平台为例&#xff0c;提供代码)HDF 框架下的 GP…

为什么jvm需要有栈协程?

旧有的servlet生态的线程模型 首先我们先要聊一聊现在我们用的最多的servlet的执行模型是什么&#xff1a; 这个dispatch其实就是一个EventLoop或者说是一个selector来检测注册到其上的链接状态发生的变化 以Tomcat为例子&#xff0c;当这个selector发现存在一个链接可读时&…

【node.js】fs\path\http模块的使用

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;Node.js的fs\path\http模块的使用&#xff0c;模块化开发概念 目录 一、node.js概念与作…

一个曾经分享动态(2021)的回顾和解释-2023-

虽然看过一些典故&#xff0c;里面有名言道&#xff1a; 解释永远是多余的&#xff0c;理解的人不需要&#xff0c;不理解的更不需要。 但是&#xff0c;误会还是需要沟通来消除的。 例如&#xff0c;曾经分享过&#xff1a; 如下都是误会 ↓↓↓↓↓↓↓↓↓ 有朋友联系我&a…

解决东方财富数据接口激活后仍显示reactive的问题

首先确保代码可以在python中导入这个包&#xff1a; from EmQuantAPI import c如果无法导入&#xff0c;就是python没有配置好东方财富的接口&#xff0c;可以参考&#xff1a; Mac版本&#xff1a;Mac使用Python接入东方财富量化接口Choice&#xff0c;调试与获取数据Window…

北京智和信通:信创运维自动化,全栈适配国产软硬件环境

近年来&#xff0c;新基建和信创产业政策东风席卷神州&#xff0c;国产CPU、操作系统、关键应用软件等核心技术步入发展快车道&#xff0c;一批优秀软硬件产品走进政府机关、国企事业单位。在国产软硬件核心技术崛起的过程中&#xff0c;如何迅速搭建起成熟的生态环境是行业面临…

LeetCode135之分发糖果(相关话题:数组,贪心思想)

题目描述 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算并返回需…

【node.js】跨域的解决办法(CORS方法、同源策列的理解)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;面对cors跨域、同源策略的处理 下图为本文的核心 目录 一、 跨域介绍 二、同源策略 三…

正态分布与numpy.random.normal函数

文章目录1. 正态分布2. numpy.random.normal函数3. 示例在Numpy中&#xff0c;有一个专门用于生成符合正态分布的随机数函数&#xff1a;numpy.random.normal&#xff0c;本文我们梳理一下它的使用方法&#xff0c;在梳理前&#xff0c;需要先了解一下什么是正态分布。 1. 正态…

黑马Hive+Spark离线数仓工业项目-任务流调度工具AirFlow(1)

任务流调度工具AirFlow 1. AirFlow介绍【了解】 - 功能、特点 - 架构角色、安装部署 2. **AirFlow使用【掌握】** - 核心&#xff1a;调度脚本【Python | Shell】 - 定时调度&#xff1a;Linux Crontab表达式 - 邮件告警&#xff1a;配置 3. 回顾Spark核心概念 - 存…

【10个基本网络故障排查工具-每个IT专业人员应了解】

网络故障排除工具是每个网络管理员的必需品。 在网络领域入门时&#xff0c;重要的是要积累一些可用于解决各种不同网络状况的工具。 虽然特定工具的使用确实是主观的并且由工程师自行决定&#xff0c;但本文中的工具选择是基于它们的一般性和通用性。 本文回顾了可帮助您解决大…

聊聊业务项目如何主动感知mysql是否存活

前言 先前写过一篇文章聊聊如何利用redis实现多级缓存同步,里面讲到业务部门因数据库宕机&#xff0c;有技术提出当数据库宕机&#xff0c;切换到redis&#xff0c;今天我们就来聊聊如何触发这个切换动作&#xff1f; 1、方案一&#xff1a;利用异常机制 伪代码如下&#xf…

大三寒假人生第一次面试失败

2022/12/28&#xff0c;今天是人生第一次面试。坐了2个小时的地铁去面试结果却很惨。一开始进门就笔试&#xff0c;当看到笔试题时发现很多基础&#xff0c;平时耳熟能详的词汇却怎么样也回答不出来。做了一个多小时&#xff0c;当面试官把题改了以后一句笔试没过。说真的在出门…

RocketMQ消息队列的下载、配置、启动、测试

目录 下载 环境变量的配置 新建一个变量 配置path 新建变量 启动 命名服务器 启动broker 测试是否启动成功 下载 地址&#xff1a;RocketMQ 官方网站 | RocketMQ 切换到中文模式很容易看的 下载那一列就行了 安装很容易的。 环境变量的配置 新建一个变量 就是你的bin文…

No.181# 点直播简要架构梳理走查

引言直播带货、潮流电商、短视频不断融合&#xff0c;本文走查下音视频直播的简要架构和角色。选择UDP&#xff0c;注重传输实时性&#xff0c;在线教育、音视频会议等。选择TCP&#xff0c;注重画面质量、是否卡顿等&#xff0c;娱乐直播、直播带货等。本文主要内容有&#xf…

RPA:帮助企业完成财务数字化转型

为什么要做财务的数字化转型 a. 传统企业财务的现状 “重复性强、耗时耗力、效率低下”是目前大家对传统企业财务的固有印象。很多企业的财务部门仍然采用传统的手工操作模式&#xff0c;财务流程繁琐分散&#xff0c;且财务部门缺乏获取、处理数据的工具。绝大部分的人力都投…

2022LOL微博杯模糊问题,1080p高清看微博杯the shy比赛直播

2022LOL微博杯的直播模糊&#xff0c;看着不爽 观看方法 1.打开下面在线播放m3u8文件的地址 http://www.m3u8.zone/ 如图 2.输入播放地址 微博杯的播放地址&#xff1a; &#xff08;1月三号的地址 如果失效往下看解决方法&#xff09; https://plwb01.live.weibo.com/ali…

前端数据结构与算法

前端数据结构与算法 文章宝典 链表 可以快速删除和插入节点&#xff0c;只用修改节点的引用 实例 队列 实例 栈 实例 树 并且左节点的值和后续节点的值都要小于等于该节点的值 图 根据图的节点之间的边是否有方向&#xff0c;可以分为有向图和无向图。 在有向图…

数字调制系列:如何理解IQ ?

最近在筹划写一系列关于数字IQ 调制的短文&#xff0c;以帮助初学者能够更好地理解和掌握。虽然IQ 调制技术已经非常广泛地应用于各种无线通信应用中&#xff0c;但是究其细节&#xff0c;仍有很多人存在疑惑&#xff0c;尤其对于初学者。作者从事测试工作多年&#xff0c;对IQ…