【Java 基础篇】Java JUnit 使用详解

在这里插入图片描述

JUnit是一个用于编写和运行单元测试的Java框架。它是开发高质量、可维护和可扩展的Java应用程序的关键工具之一。本文将详细介绍JUnit的使用,包括JUnit的安装、基本用法、常见注解、测试套件、参数化测试等内容。

什么是单元测试?

在深入JUnit之前,让我们首先了解一下什么是单元测试。单元测试是一种软件测试方法,用于验证应用程序中的最小代码单元(通常是一个函数、方法或类)是否按照预期工作。单元测试的目的是隔离代码的不同部分并确保它们在独立测试时按照规范运行。

JUnit的安装

要使用JUnit,首先需要将JUnit库添加到您的项目中。可以通过以下两种方式之一进行安装:

方法一:手动下载并添加JUnit库

  1. 访问JUnit的官方网站:https://junit.org/junit5/。

  2. 下载JUnit的JAR文件(通常是junit-platform-console-standalone.jar)。

  3. 将下载的JAR文件添加到您的项目中的类路径中。

方法二:使用构建工具(如Maven或Gradle)

如果您的项目使用Maven或Gradle等构建工具,可以很容易地添加JUnit依赖。以下是使用Maven的示例:

Maven:

在项目的pom.xml文件中,添加以下JUnit依赖:

<dependencies><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.7.2</version> <!-- 可以根据最新版本进行更新 --><scope>test</scope></dependency>
</dependencies>

Gradle用户可以通过在build.gradle文件中添加相应的依赖来完成类似的操作。

基本用法

一旦您的项目配置好了JUnit,就可以开始编写测试用例了。JUnit使用注解来标识测试方法,以下是一个简单的示例:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;public class MyMathTest {@Testpublic void testAdd() {MyMath math = new MyMath();int result = math.add(2, 3);assertEquals(5, result);}
}

在上面的示例中,我们创建了一个名为MyMathTest的测试类,其中包含一个名为testAdd的测试方法。该方法使用assertEquals断言来检查math.add(2, 3)的结果是否等于5。如果不等于5,测试将失败。

要运行这个测试,您可以使用您的IDE(如Eclipse或IntelliJ IDEA)或者使用命令行工具执行JUnit测试。通常情况下,JUnit测试类的命名约定是在类名后面添加Test,这有助于JUnit自动识别测试类。

常见JUnit注解

JUnit使用各种注解来控制测试的行为和配置。以下是一些常用的JUnit注解:

@Test

@Test注解用于标识测试方法。JUnit将执行所有带有@Test注解的方法,并报告测试结果。

@Test
public void testAdd() {// 测试代码
}

@Before@After

@Before@After注解用于在测试方法之前和之后执行一些设置或清理工作。这对于准备测试环境和资源的初始化非常有用。

@Before
public void setUp() {// 执行测试前的准备工作
}@After
public void tearDown() {// 执行测试后的清理工作
}

@BeforeEach@AfterEach

@BeforeEach@AfterEach注解与@Before@After类似,但它们在每个测试方法之前和之后执行,而不是在测试类级别执行。

@BeforeEach
public void init() {// 在每个测试方法前执行初始化
}@AfterEach
public void cleanup() {// 在每个测试方法后执行清理工作
}

@BeforeAll@AfterAll

@BeforeAll@AfterAll注解用于在测试类中的所有测试方法之前和之后执行一次。通常用于执行全局初始化和清理工作。

@BeforeAll
public static void initAll() {// 在所有测试方法前执行初始化
}@AfterAll
public static void tearDownAll() {// 在所有测试方法后执行清理工作
}

@Disabled

@Disabled注解用于禁用测试方法。被标记为@Disabled的测试方法不会被执行。

@Disabled
@Test
public void disabledTest() {// 这个测试方法被禁用
}

其它JUnit注解

除了上面介绍的常用JUnit注解之外,JUnit 5还提供了一些其他有用的注解,可以用于测试和测试方法的各种配置和控制。以下是一些其他常用的JUnit注解:

@Timeout

@Timeout注解用于指定测试方法的超时时间。如果测试方法执行时间超过指定的超时时间,测试将被标记为失败。

@Test
@Timeout(2) // 指定超时时间为2秒
public void testWithTimeout() throws InterruptedException {Thread.sleep(3000); // 这个测试方法将会失败,因为执行时间超过了2秒
}

@RepeatedTest

@RepeatedTest注解用于重复运行相同的测试方法多次。

@RepeatedTest(3) // 重复运行3次
public void repeatedTest() {// 这个测试方法将会被运行3次
}

@Tag

@Tag注解用于为测试类或测试方法添加标签。标签可以用于组织和筛选测试,例如只运行特定标签的测试。

@Tag("integration") // 给测试方法添加一个名为"integration"的标签
@Test
public void integrationTest() {// 这个测试方法被标记为"integration"标签
}

@DisplayName

@DisplayName注解用于为测试类或测试方法指定自定义的显示名称,用于更清晰地描述测试的目的。

@DisplayName("Custom Display Name") // 自定义显示名称
@Test
public void customDisplayNameTest() {// ...
}

@ExtendWith

@ExtendWith注解用于指定扩展,扩展是JUnit 5中的插件机制,可以扩展测试框架的功能。常见的扩展包括参数解析、条件测试、测试拦截等。

@ExtendWith(MyExtension.class) // 使用自定义扩展
@Test
public void testWithCustomExtension() {// ...
}

这些是JUnit 5中的一些其他常用注解,它们可以帮助您更灵活地控制和配置测试。根据您的测试需求,可以选择适当的注解来优化测试代码。

测试套件

测试套件是一种将多个测试类组合在一起运行的方式。JUnit 5引入了更灵活的测试套件机制,通过@RunWith注解来定义测试套件已经不再需要。

要创建一个测试套件,可以使用@SelectClasses注解来指定要包括在套件中的测试类,然后使用@RunWith注解运行测试套件。

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;@Suite
@SelectClasses({TestClass1.class, TestClass2.class})
public class TestSuite {// 这里不需要编写任何代码
}

参数化测试

JUnit 5引入了参数化测试的概念,使您可以轻松地运行相同的测试方法多次,但使用不同的输入参数。这对于测试具有多个输入组合的方法非常有用。

要创建参数化测试,您可以使用@ParameterizedTest注解,然后提供测试参数和测试工厂方法。

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;public class ParameterizedMathTest {@ParameterizedTest@CsvSource({"2, 3, 5", "5, 7, 12", "10, 0, 10"})public void testAdd(int a, int b, int expected) {MyMath math = new MyMath();int result = math.add(a, b);assertEquals(expected, result);}
}

在上面的示例中,@CsvSource提供了测试参数,每个参数组由逗号分隔。参数化测试将会对每组参数运行测试方法,并验证是否符合预期的结果。

案例讲解

以下是一个简单的JUnit 5注解的示例,演示如何使用JUnit来测试一个简单的Calculator类:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;public class CalculatorTest {private Calculator calculator;@BeforeEachvoid setUp() {// 在每个测试方法之前初始化Calculator对象calculator = new Calculator();}@Testvoid testAddition() {int result = calculator.add(2, 3);assertEquals(5, result); // 验证相等}@Testvoid testSubtraction() {int result = calculator.subtract(5, 3);assertEquals(2, result); // 验证相等}@Testvoid testMultiplication() {int result = calculator.multiply(2, 3);assertEquals(6, result); // 验证相等}@Testvoid testDivision() {int result = calculator.divide(6, 2);assertEquals(3, result); // 验证相等}@Testvoid testDivisionByZero() {assertThrows(ArithmeticException.class, () -> calculator.divide(5, 0));}
}

在这个示例中,我们使用了以下JUnit注解:

  • @BeforeEach:用于标记在每个测试方法之前执行的方法。在此示例中,我们在每个测试方法之前初始化Calculator对象。
  • @Test:用于标记测试方法。每个测试方法都应以@Test注解进行标记。
  • assertEquals:JUnit的断言方法之一,用于验证预期值和实际值是否相等。
  • assertThrows:JUnit的断言方法之一,用于验证是否抛出了预期的异常。

这个示例测试了一个Calculator类的基本数学运算方法,包括加法、减法、乘法、除法以及除零操作。JUnit通过注解和断言来简化测试,并提供了测试报告和结果的详细信息。

注意事项

在使用JUnit进行单元测试时,有一些注意事项和最佳实践,以确保测试的准确性和可维护性。以下是一些常见的JUnit使用注意事项:

  1. 命名规范:使用有意义的命名来标识测试方法和测试类。通常,测试方法的名称应以test开头,并描述被测试方法的行为。

    @Test
    void testCalculateTotalAmount() {// 测试方法的名称应描述被测试方法的行为
    }
    
  2. 独立性:每个测试方法应该是相互独立的,不应该依赖于其他测试方法的状态。每个测试方法应该在一个干净的环境中运行,不受其他测试方法的影响。

  3. 注释和文档:为测试方法和测试类添加清晰的注释和文档,以解释测试的目的和预期行为。这将有助于其他开发人员理解测试的意图。

  4. 断言:使用适当的断言来验证被测试方法的行为。JUnit提供了多种断言方法,如assertEqualsassertTrueassertNotNull等,根据需要选择合适的断言。

    @Test
    void testAddition() {int result = calculator.add(2, 3);assertEquals(5, result); // 验证相等
    }
    
  5. 异常测试:对于可能抛出异常的方法,编写相应的异常测试。使用assertThrows来验证是否抛出了预期的异常。

    @Test
    void testDivisionByZero() {assertThrows(ArithmeticException.class, () -> calculator.divide(5, 0));
    }
    
  6. 组织测试:使用JUnit的@BeforeAll@BeforeEach@AfterEach@AfterAll注解来执行一次性的准备和清理工作,以及在每个测试方法前后执行的操作。

    @BeforeEach
    void setUp() {// 在每个测试方法之前执行
    }@AfterEach
    void tearDown() {// 在每个测试方法之后执行
    }
    
  7. 测试顺序:默认情况下,JUnit不保证测试方法的执行顺序。确保您的测试方法是独立的,不依赖于执行顺序。

  8. 测试套件:JUnit允许您创建测试套件,将一组相关的测试类组合在一起运行。这对于执行整个测试集合非常有用。

  9. 参数化测试:JUnit 5支持参数化测试,允许您运行相同的测试方法多次,但使用不同的输入参数。这可以大大减少代码冗余。

  10. 超时设置:在测试方法上使用@Timeout注解可以设置测试方法的最大执行时间,以避免无限等待。

@Test
@Timeout(5) // 设置最大执行时间为5秒
void testTimeout() {// ...
}
  1. 忽略测试:在开发过程中,有时您可能需要忽略某些测试。您可以使用@Disabled注解来禁用测试方法。
@Disabled
@Test
void testDisabled() {// 这个测试方法被禁用
}
  1. 使用Mock对象:当测试依赖于外部资源或其他类时,考虑使用Mock对象来模拟这些依赖,以隔离测试并使其更可靠。

这些注意事项可以帮助您编写更好的JUnit单元测试,确保测试的可维护性和可靠性。根据项目的需求,还可以进一步探索JUnit的高级功能和扩展。

结语

JUnit是Java开发中必不可少的测试框架之一,它可以帮助您编写高质量、可维护的单元测试。本文介绍了JUnit的基本用法、常用注解、测试套件和参数化测试等内容,希望对您的测试工作有所帮助。在实际项目中,合理的单元测试可以提高代码的质量、可靠性和可维护性,因此请养成编写单元测试的习惯。

作者信息

作者 : 繁依Fanyi
CSDN: https://techfanyi.blog.csdn.net
掘金:https://juejin.cn/user/4154386571867191

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

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

相关文章

【深度学习实验】卷积神经网络(二):自定义简单的二维卷积神经网络

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 二维互相关运算&#xff08;corr2d&#xff09; 2. 二维卷积层类&#xff08;Conv2D&#xff09; a. __init__&#xff08;初始化&#xff09; b. forward(前向传…

web浏览器公网远程访问jupyter notebook【内网穿透】

文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook&#xff0c;它是一个交互式的数据科学和计算环境&#xff0c;支持多种编程语言&#xff0c;如…

【数据结构-树】哈夫曼树

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

【算法思想-排序】根据另一个数组次序排序 - 力扣 1122 题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

超越代写!5步教你轻松利用ChatGPT创作文本

任何尝试用 ChatGPT 写过“写一篇关于【主题】的文章”的人都知道一个真相&#xff1a; ChatGPT 根本写不好&#xff0c;这不是秘密。如果你怀疑我&#xff0c;试试用它或者任何 AI 写作工具去写一篇博客文章&#xff0c;结果它都会写出非常糟糕的、没人会想看的内容。 但是我…

springboot基于SpringBoot的冬奥会科普平台springboot21

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

基于微信小程序的动漫论坛平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

RocketMQ生产环境常见问题分析与总结

关于零拷贝与顺序写 一、RocketMQ如何保证消息不丢失 1、哪些环节会有丢消息的可能&#xff1f; 我们考虑一个通用的MQ场景&#xff1a; 其中&#xff0c;1&#xff0c;2&#xff0c;4三个场景都是跨网络的&#xff0c;而跨网络就肯定会有丢消息的可能。 然后关于3这个环节…

地球的某一片红薯地中秋圆《乡村振兴战略下传统村落文化旅游设计》——旅行季许少辉八月新书辉少许想象和世界一样宽广

地球的某一片红薯地中秋圆《乡村振兴战略下传统村落文化旅游设计》——旅行季许少辉八月新书辉少许想象和世界一样宽广 地球的某一片红薯地中秋圆《乡村振兴战略下传统村落文化旅游设计》——旅行季许少辉八月新书辉少许想象和世界一样宽广]

JetBrains常用插件

Codota AI Autocomplete Java and JavaScript&#xff1a;自动补全插件 Background Image plus&#xff1a;背景图片设置 rainbow brackets&#xff1a;彩虹括号&#xff0c;便于识别 CodeGlance2&#xff1a; 类似于 Sublime 中的代码缩略图&#xff08;代码小地图&#xff…

什么是Redux?它的核心概念有哪些?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是Redux&#xff1f;⭐ 它的核心概念有哪些&#xff1f;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发…

如何通过bat批处理实现快速生成文件目录,一键生成文件名和文件夹名目录

碰对了情人&#xff0c;相思一辈子。 具体方法步骤&#xff1a; 一、创建一个执行bat文件&#xff08;使用记事本即可&#xff09;&#xff1b; 1、新建一个txt文本空白记事本文件 2、复制以下内容进记事本内 dir/a/s/b>LIST.TXT &#xff08;其中LIST.TXT文件名是提取后将…

【Go】rsrc不是内部或外部命令、无法将“rsrc”项识别为 cmdlet、函数、脚本文件或可运行程序的名称 解决方法

前言 想尝试用go创建一个桌面应用程序&#xff0c;然后查了下决定用 walk。 我们要先下载walk&#xff0c;这里 官方链接 按照官方文档&#xff0c;我们先用go get命令下载。 go get github.com/lxn/walk然后分别创建好了 main.go、main.manifest 文件&#xff0c;代码如下…

CV经典任务(一) 语义分割、实例分割 | 全卷积

文章目录 1 语义分割1.1 思路1 滑动窗口1.2 思路2 全卷积网络 2 代码实现3 实例分割 之前讲了分类 实际中除了分类还有几大视觉任务 语义分割&#xff0c;实例分割&#xff0c;目标检测 以上任务基本也都基于前面讲的卷积网络去做的 1 语义分割 语义分割&#xff08;Semant…

深度学习:模型训练过程中Trying to backward through the graph a second time解决方案

1 问题描述 在训练lstm网络过程中出现如下错误&#xff1a; Traceback (most recent call last):File "D:\code\lstm_emotion_analyse\text_analyse.py", line 82, in <module>loss.backward()File "C:\Users\lishu\anaconda3\envs\pt2\lib\site-packag…

常用的文本对比工具或网站

以下是一些常用的文本对比工具的下载地址或网站访问地址&#xff1a; DiffNow: https://www.diffnow.com/ WinMerge: https://winmerge.org/ Beyond Compare: https://www.scootersoftware.com/ Meld: https://meldmerge.org/ diff:文本对比/字符串差异比较 - 在线工具 请…

vite.config.ts

vite会自动生成vite.config.ts文件 https://juejin.cn/post/7039879176534360077https://juejin.cn/post/7039879176534360077 挑了几个常用的记下笔记&#xff0c;配置别名&#xff0c;proxy跨域&#xff0c;本地服务设置 import { defineConfig } from vite import vue fr…

Java环形链表(图文详解)

目录 一、判断链表中是否有环 &#xff08;1&#xff09;题目描述 &#xff08;2&#xff09;题解 二、环形链表的入环节点 &#xff08;1&#xff09;题目描述 &#xff08;2&#xff09;题解 一、判断链表中是否有环 &#xff08;1&#xff09;题目描述 给你一个链表的…

构建智能客服知识库,优化客户体验不是难题!

在当今快节奏的商业环境中&#xff0c;客户都希望得到及时个性化的支持&#xff0c;拥有一个智能客服知识库对于现代企业至关重要。智能客服知识库是一个集中存储、组织和访问与客户服务互动相关的信息的综合性知识库。它为企业提供了全面的知识来源&#xff0c;使他们能够为客…

想要精通算法和SQL的成长之路 - 最长递增子序列 II(线段树的运用)

想要精通算法和SQL的成长之路 - 最长递增子序列 II&#xff08;线段树的运用&#xff09; 前言一. 最长递增子序列 II1.1 向下递推1.2 向上递推1.3 更新操作1.4 查询操作1.5 完整代码&#xff1a; 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 最长递增子序列 II 原题链接…