如何写Java单元测试

article/2025/9/11 0:54:59

本文引自https://www.cnblogs.com/ysw-go/p/5447056.html

什么是单元测试
  我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的。但是,我们同时应该确保每一个函数都完全正确,因为如果我们今后如果对程序进行扩展,用到了某个函数的其他功能,而这个功能有bug的话,那绝对是一件非常郁闷的事情。所以说,每编写完一个函数之后,都应该对这个函数的方方面面进行测试,这样的测试我们称之为单元测试。传统的编程方式,进行单元测试是一件很麻烦的事情,你要重新写另外一个程序,在该程序中调用你需要测试的方法,并且仔细观察运行结果,看看是否有错。这样的话太过于麻烦了,本文简要介绍一下在Eclipse中使用JUnit4进行单元测试的方法。用更加通俗的话来描述单元测试就是:写了个类,要给别人用,会不会有bug?怎么办?测试一下。用main方法测试好不好?这种方法我们经常用,就是写一个方法实现一些功能,把方法的调用方式放在main函数中。这样的测试方式一个是使得main函数太过于混乱,再者测试过程需要人的仔细观察来辨别每个函数的功能实现,哪一个函数出错了,哪一个函数没有输出之类的问题层出不穷,单元测试就是来解决这些问题的。下面我会就单元测试的每一步给出详细的图解和描述。

第一部分

我们先创建一个Java Project,名字就叫做JUnit4,然后创建两个包com.itcast.junit4和com.itcast.junit4.test,如下图所示
在这里插入图片描述
其中com.itcast.junit4用于我们自己写的类和方法的存放,com.itcast.junit4.test用于我们完成单元测试

在com.itcast.junit4包中创建一个类叫做T(名字可以是任意的,这里是为了方便),在类中添加两个方法add和divide实现两个数的加法和除法运算

package com.itcast.junit4;public class T {public int add(int x,int y){return x+y;}public int divide(int x,int y){return x/y;}public static void main(String[] args) {int z=new T().add(3, 5);System.out.println(z);}} 

我们传统测试的方法通常都是按上面的方式去看add函数是否可以实现我们想要的功能,把方法的调用放在main函数中。下面我们看一下单元测试到底是什么东西:
在com.itcast.junit4.test包中创建一个类,叫做TTest(单元测试命名规范:a) 类放在test包中;b) 类名用XXXTest结尾;c) 方法用testMethod命名;)
在这里插入图片描述
【步骤提示】com.itcast.junit4.test包–>右键–>New–Junit Test Case,然后选择New Junit 4 test,那个Junit 3已经过时了。下面的一行Class under test,单击右侧的Browser,在弹出的输入框中输入我们想要测试的类名T,选中单击next出现了一个界面要我们选择需要测试的方法,我们这里选择add方法和divide;
在这里插入图片描述
在这里插入图片描述
接着出现了下面的界面:
在这里插入图片描述
这一步提示我们是否将我们需要的JUnit 4的相关包加入到我们项目的ClassPath路径下,点击OK就行,因为Eclipse中包含JUnit的jar包,我们暂且先用Eclipse自带的Junit4去测试,后面后将如何用我们自己下载的JUnit4 JAR包。

做完上面的步骤会创建一个这样的测试类

import static org.junit.Assert.*;import org.junit.Test;public class TTest {@Testpublic void testAdd() {fail("Not yet implemented");}@Testpublic void testDivide() {fail("Not yet implemented");}} 

上面的org.junit.Assert.*;就是静态导入的我们实现单元测试要用到的一些方法;【注意】这是静态引入,可以把方法直接引入,org.junit.Assert是一个类,不是一个包,当然这些方法肯定都是静态方法了。出现的代码都是Assert类中的一些方法,"@Test”表明下面这个方法是一个测试方法,我们先删除自动生成的fail()函数的代码。添加以下代码:

public class TTest {@Testpublic void testAdd() {int z=new T().add(2, 4);//判断z==6,以往的assertassertEquals(6, z);}@Testpublic void testDivide() {//测试T类中的divide方法int z=new T().divide(8, 2);System.out.println(z);}}

我们现在开始进行测试:要测试的方法–>右键–>Run As–>JUnit Test
在这里插入图片描述
如果你想两个方法一块测试,则Run As–>选择Run Configurations:按图中选择相应的选项,然后点击Run
在这里插入图片描述
点击run会出现下面的结果:
在这里插入图片描述
绿条显示两个方法的功能没有错误,有这样的调试准则:keep the bar green,to keep the code clean,绿色代表测试成功,其中Error:程序出错 Failures:测试失败

Error:是程序有问题,比如我们在testAdd方法中加上这一句:int a=8/0;再次测试这个方法则会出现一个Error

public void testAdd() {int z=new T().add(2, 4);//判断z==6,以往的assertassertEquals(6, z);int a=8/0;
}

在这里插入图片描述
可以看到最下方提示我们,我们写的方法中出现了除数为0的情况

Failures:测试失败,比如我们在方法改成下面的形式:

public void testAdd() {int z=new T().add(2, 4);//判断z==6,以往的assertassertEquals(6, z);assertTrue(z<3);
//        int a=8/0;
}

再次测试一下我们的方法:则会出现调试失败的情况
在这里插入图片描述

第二部分

通过上面的学习我们已经了解基本的单元测试的步骤,我们查看一下JUnit API可以看到org.junit.Assert类有很多类似于assertEquals(6, z);assertTrue(z<3);之类的方法的使用;
在这里插入图片描述
我们可以看到有很多方法都是以重载的形式出现的,比如我们前面的例子,在testAdd()方法中添加assertTrue(“z too small”,z>10);前面的字符串用于在我们测试失败的情况下给我们提示:因为8<10,所以会在测试失败的情况下给我们提示"z too small";

重磅出击:assertThat

assertThat(来自hamcrest包,所以我们需要下载hamcrest这个包,这里共享给大家,里面有很多我们平时都可以用到的JAR包和文件,地址:链接:http://pan.baidu.com/s/1sl02DOD 密码:ci5m): assertThat(actual, matcher);的出现可以替代其他所有的assert。放弃旧的断言,使用hamcrest断言。其中actual参数是实际的值,matcher可以是一个匹配器。在以后的项目开发中我们就可以使用assertThat代替前面出现的类如assertEquals(6, z); assertTrue(z<3);方法。

首先第一步,我们想使用assertThat,需要添加两个jar包hamcrest-core-1.2和hamcrest-library-1.2,这两个包都在我的共享里了,想在把这两个包添加进我们的Java Project中JUnit4 Test–>右键–>Build Path–>Add External Archives,将这两个Jar加进去
在这里插入图片描述
添加以后:我们就可以使用assertThat了
在这里插入图片描述
我们把testAdd()方法改成下面的形式:

    @Testpublic void testAdd() {int z=new T().add(2, 4);assertThat(z, is(8));//判断z==6,以往的assert
//        assertEquals(6, z);
//        assertTrue(z<3);
//        int a=8/0;}

代码中的is()方法是在import static org.hamcrest.Matchers(这个类在我们加进来的hamcrest-core-1.2.jar内)类的一个方法我们需要将其静态引入,所以在最上面要加上下面这一句,应该就可以了;

import static org.hamcrest.Matchers.*;

但是,测试又出现了这样的错误:
在这里插入图片描述
我们可以看到Failure Trace第一行什么ClassLoader的错误,这是因为我们在这里用了两种包,一个是hamcrest包,一个是JUnit4的包,这两个包它们的ClassLoader用的不是一个(不清楚啥是ClassLoader,不要紧,先学会怎么解决,以后再研究)。解决方法很简单:在我们的JUnit4项目中–>右键JUnit->Build Path–>Remove from Build Path即可,如图所示:
在这里插入图片描述
然后我们自己将JUnit包引入进来(Junit也在我的分享文件中)

JUnit4 Test–>右键–>Build Path–>Add External Archives,选择我们JUnit包中的junit-4.10,如下图所示:
在这里插入图片描述
ok!测试成功!

assert的使用是测试代码更加自然(诸如这样的理解:z is 8),自己可以体会一下,下面给出一些实例,大家可以自己动手试一下

示例
a)assertThat( n, allOf( greaterThan(1), lessThan(15) ) );
assertThat( n, anyOf( greaterThan(16), lessThan(8) ) );
assertThat( n, anything() );
assertThat( str, is( "bjsxt" ) );
assertThat( str, not( "bjxxt" ) );b)assertThat( str, containsString( "bjsxt" ) );
assertThat( str, endsWith("bjsxt" ) );
assertThat( str, startsWith( "bjsxt" ) );
assertThat( n, equalTo( nExpected ) );
assertThat( str, equalToIgnoringCase( "bjsxt" ) );
assertThat( str, equalToIgnoringWhiteSpace( "bjsxt" ) );c)assertThat( d, closeTo( 3.0, 0.3 ) );
assertThat( d, greaterThan(3.0) );
assertThat( d, lessThan (10.0) );
assertThat( d, greaterThanOrEqualTo (5.0) );
assertThat( d, lessThanOrEqualTo (16.0) );d)assertThat( map, hasEntry( "bjsxt", "bjsxt" ) );
assertThat( iterable, hasItem ( "bjsxt" ) );
assertThat( map, hasKey ( "bjsxt" ) );
assertThat( map, hasValue ( "bjsxt" ) );

第三部分 JUnit4 Annotation

几种常见的注释形式:

@Test: 测试方法a) (expected=XXException.class)b) (timeout=xxx)@Ignore: 被忽略的测试方法@Before: 每一个测试方法之前运行@After: 每一个测试方法之后运行@BeforeClass: 所有测试开始之前运行
@AfterClass: 所有测试结束之后运行

我们分别进行解释

1)@Test,前面已经说明了,@Test注解表明下面的方法是一个测试方法,a), b)两种形式,比如@Test(expected=java.lang.ArithmeticException.class,timeout=100)a是在测试出现异常的情况下告知我们出现的异常信息,类似与try-catch中的e.printstacktrace() 方法,比较简单。b中的timeout=100,运行时间限制在100ms以内(通常在测试代码运行效率时这样设置)

2)@ignore: 被忽略的测试方法(就是测试的时候跳过ignor标记的模块或方法)
有时候某些方法还不具备测试的条件,暂时还不能测试或者某些方法已经不需要再做测试了,这就可以进行忽略的操作了。
有时方法的测试条件还没满足,整个项目还差一个模块,则可以采用该方法假定测试条件成立。

3)@after和@before

我们把代码改成这个样子:为方便起见先把那个divide方法删掉

public class TTest {@Beforepublic void before() {System.out.println("befor");}@Testpublic void testAdd() {int z = new T().add(2, 4);assertThat(z, is(8));// 判断z==6,以往的assert// assertEquals(6, z);// assertTrue(z<3);// int a=8/0;}@Afterpublic void after() {System.out.println("after");}}

当然需要在上面需要添加这两句:

import org.junit.After;
import org.junit.Before;

测试一下我们的testAdd()方法,控制台输出:

befor
after

说明@Before在每一个测试方法(@Test方法)之前运行 @After:在每一个测试方法之后运行。它们两个的应用场合: 有些方法需要执行的时候需要一些先决条件,比如打开某文件、获取资源,搭建环境,执行完之后需要关闭文件、释放资源、卸载环境这就需要before和after操作。

4)@BeforeClass;@AfterClass,它们两个都是静态的方法。我们继续改写代码:

public class TTest {@BeforeClasspublic static void beforeClass(){System.out.println("before class..");}@Beforepublic void before() {System.out.println("befor");}@Testpublic void testAdd() {int z = new T().add(2, 4);assertThat(z, is(6));// 判断z==6,以往的assert// assertEquals(6, z);// assertTrue(z<3);// int a=8/0;}@Afterpublic void after() {System.out.println("after");}@AfterClasspublic static void afterClass(){System.out.println("after class..");}}

当然也要加上:

import org.junit.BeforeClass;
import org.junit.AfterClass;

输出结果:

before class..
befor
after
after class..

这就说明了@BeforeClass 所有测试开始之前运行;@AfterClass: 所有测试结束之后运行【一定要注意】这两个方法都是静态方法,想想也应该明白类一加载就执行这两个方法,此时还没有创建任何对象,能执行的肯定就是静态方法了。

总结:

用了一天的时间学习了一下JUnit单元测试,其实还有很多东西没有看到,但对于单元测试的步骤和套路也算了解了一些,写在这里也方便自己以后的查阅和复习,待以后用到更深入的时候再更新一些单元测试在Spring/Mock中的应用,有错误的地方欢迎大家指出,再次谢谢大家的阅读!


http://chatgpt.dhexx.cn/article/lRMGxusM.shtml

相关文章

Java单元测试总结

[版权申明] 非商业目的注明出处可自由转载 博文地址&#xff1a; 出自&#xff1a;shusheng007 文章目录 概述单元测试概念测试项目单元测试工具JUnitMockito SpringBoot测试总结 概述 关于为什么要做单元测试是老生常谈了&#xff0c;越是小公司越不重视单元测试&#xff0c;…

java单元测试junit

进行单元测试则需要添加junit的依赖&#xff1a; ##JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck. ##对于java来说JUnit是一个单元测试的框架<dependency><groupId>junit</groupId><artifactId>junit</arti…

Java 单元测试

什么是单元测试 单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证&#xff0c;简单来说就是测试部分代码&#xff0c;对代码中的问题快速定位&#xff0c;及时修复。 什么是JUnit JUnit就是一个Java语言的单元测试框架…

JAVA基础之单元测试

目录 1、单元测试介绍 2、环境搭建 2.1 JUnit 4 2.2 JUnit 5 3、快速上手 3.1 JUnit 4 3.2 JUnit 5 1、单元测试介绍 单元测试就是针对最小的功能单元编写测试代码&#xff0c;Java程序最小的功能单元是方法&#xff0c;因此&#xff0c;单元测试就是针对Java方法的测试…

Java基础单元测试

本篇博文目录: 1.单元测试(1) 测试Java方法(原生) 2. JUnit 5(1) JUnit 5简单使用的例子(2) JUnit5常用注解(3) JUnit5常用注解的使用(4).JUnit5内置断言 1.单元测试 单元测试就是针对最小的功能单元编写测试代码。Java程序最小的功能单元是方法&#xff0c;因此&#xff0c;对…

如何进行Java 单元测试

一、概述 Java 单元测试是指对软件中的最小可测试单元进行测试&#xff0c;以保证代码的质量和正确性&#xff0c;并且可以加速开发过程。本文将全面详细地介绍 Java 单元测试相关知识点&#xff0c;包括单元测试的定义、优点和流程、JUnit 测试框架、Mockito 框架、持续集成、…

Java之单元测试(JUnit单元测试框架)

一、概述 单元测试就是针对最小的功能单元编写测试代码&#xff0c;Java程序最小的功能单元是方法&#xff0c;所以单元测试就是针对Java方法的测试&#xff0c;进而检查方法的正确性。常规测试有什么问题&#xff1f; 只有一个main方法&#xff0c;如果一个方法的测试失败了…

(60)Java基础 --单元测试

目录 一、测试的概念 二、使用Junit4.x进行单元环境 1、环境搭建 2、使用步骤 3、常见注解 三、规范的Junit测试方式 四、断言 1、为什么要使用断言 2、什么是断言(猜测) 3、常用API 一、测试的概念 先认识到测试的重要性&#xff1a;优秀的软件不是开发出来的,而是…

微信小程序消息推送(订阅消息原模板消息)开发流程

注&#xff1a;模板消息没了。 正常开发肯定需要前后端配合&#xff0c;此处都在小程序里写了 参考文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html 订阅消息是个很好的功能&#xff0c;但是现在被不良商家…

小程序之模版消息通知

手把手教你开发微信小程序之模版消息通知 一、模板消息功能概述 模板推送位置&#xff1a;服务通知 模板消息效果展示图&#xff1a; 进入小程序通知&#xff1a; 二、开发前的配置准备 1、验证token是否有效 <?php/*** 验证*/public function valid(){$echoStr $_GET…

java 微信小程序-发送模板消息

开发前准备工作 登录微信公众平台-小程序后台&#xff0c;在模板消息里面设置需要发送的模板&#xff0c;拿到模板id。 地址&#xff1a; https://mp.weixin.qq.com 找到微信官方文档-小程序开发-下发小程序和公众号统一的服务消息接口。 地址&#xff1a; https://developers…

【微信小程序】模板消息推送(测试成功)。

note&#xff1a; 这几天想做微信小程序消息推送的功能&#xff0c;然后在网上找了好多教程&#xff0c;都没解决问题&#xff0c;官方文档写的教程由不够详细&#xff0c;所以走了好多弯路。 现在问题解决了&#xff0c;记录一下。 我在网上找的好多教程都不详细&#xff0c;虽…

微信小程序模板订阅消息推送

尚未接触这块之前&#xff0c;以为是比较麻烦的&#xff0c;经研究并实现后&#xff0c;大致可以分为三个阶段&#xff1a; 申请模板&#xff08;明确推送卡片的格式及内容&#xff09;前端订阅&#xff08;打开可推送开关&#xff0c;允许推送&#xff09;后端推送&#xff0…

微信小程序——发送模板消息

步骤一&#xff1a;获取模板ID 1、通过模版消息管理接口获取模版ID&#xff08;详见模版消息管理&#xff09; 2、在微信公众平台手动配置获取模版ID 登录 https://mp.weixin.qq.com 获取模板&#xff0c;如果没有合适的模板&#xff0c;可以申请添加新模板&#xff0c;审核通…

微信小程序的模板消息与小程序订阅消息

小程序订阅消息功能介绍消息能力是小程序能力中的重要组成&#xff0c;我们为开发者提供了订阅消息能力&#xff0c;以便实现服务的闭环和更优的体验。 订阅消息推送位置&#xff1a;服务通知订阅消息下发条件&#xff1a;用户自主订阅订阅消息卡片跳转能力&#xff1a;点击查…

《微信小程序——发送模板消息》详细步骤

第一步&#xff1a;获取access_token 第一步详情&#xff1a;因为access_token在微信公众号还是小程序&#xff0c;在一个月之内都有获取次数的限制&#xff0c;并且一个access_token只有2小时的有效期&#xff1b;所以每当我们获取一次access_token,就要反复利用&#xff1b;…

微信小程序给公众号发送模板消息

参考文献&#xff1a;小程序如何向公众号推送消息_fbbqt的博客-CSDN博客_小程序给公众号发信息小程序如何向公众号推送消息https://blog.csdn.net/fbbqt/article/details/122167097 前置条件&#xff1a; 微信公众号:AppId和APPSecret(必须认证) 微信小程序:AppId和APPSecret…

微信小程序模板消息实现(PHP+小程序)

参考官方文档和部分资料&#xff0c;总结小程序模板消息推送以及相关注意事项&#xff0c;楼主踩过的坑&#xff0c;特来与大家分享。 一、开发准备&#xff1a; 1. 在微信公众平台 - 小程序的模板中心申请消息模板 二、实现原理&#xff1a; 文档示例&#xff1a;小程序 接…

微信小程序订阅模板消息

1.登录管理员后台&#xff0c;订阅消息&#xff0c;选择模板或者申请模板 2. 开发管理&#xff0c;开发设置&#xff0c;开启消息推送&#xff0c;并验证服务器 3. 开发获取获取模板列表接口&#xff0c;和 测试消息发送接口 4. 前端根据接口配置授权弹窗页&#xff0c;获取用…

微信小程序|如何设置模板消息提醒

管理员如何设置模板消息提醒&#xff0c;管理员如何查看。回复用户咨询信息 使用管理员模板消息提醒&#xff0c;首先配置模板消息 第一步&#xff0c;设置模板消息&#xff0c;配送员通过微信模板消息接收配送信息&#xff0c;需要在平台——微信公众号——模板消息设置&#…