Java单元测试及常用语句
1 前言
编写Java单元测试用例,即把一段复杂的代码拆解成一系列简单的单元测试用例,并且无需启动服务,在短时间内测试代码中的处理逻辑。写好Java单元测试用例,其实就是把“复杂问题简单化,建单问题深入化“。在编写的过程中, 我们也可以对自己的代码进行一个二次检查。
以下是我总结的一些编写单元测试的好处:
1.测试代码逻辑时,不需要启动整个应用。
2.单元测试可以覆盖边界值
3.提高原有代码的复用
4.可以有效避免代码改动后,对原有逻辑的潜在影响
2 准备环境
Mockito是目前最普遍的单元测试模拟框架。Mockito可以模拟应用中依赖的复杂对象,从而把测试对象和依赖对象隔离开。PowerMock为Mockito提供了扩展功能。为模拟静态方法,final类,和私有方法等。我们选择使用以Mockito为主,PowerMock为辅的框架来做单元测试。
2.1 引入Mockito和PowerMock包,在pom.xml文件中加入以下依赖:
<properties>
<powermock.version>2.0.9</powermock.version>
</properties>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
PowerMock目前最新版本为2.0.9【PowerMock链接】由于PowerMock包中已经包含了对应的Mockito和JUnit包,所以无需再单独引入。
3 一些常用的mock语句
3.1 模拟指定类的对象实例,用于模拟依赖对象(类成员)
在Spring中,这些成员对象通过@Autowire,@Resource,@Value等方式注入,可能涉及到环境配置或者依赖第三方接口。在单元测试中,不是我们关注的点,所以可以用mock模拟
//方法一
Mockito.mock(OrderInfo.class);
//方法二
@Mock
private OrderInfo orderInfo;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
3.2 定义被测试对象
把被测试服务类进行实例化
@InjectMocks
private OrderServiceImpl orderService;
3.3 模拟枚举类型/静态方法
需要把对应的模拟类放在@PrepareForTest中
//必须添加@RunWith和@PrepareForTest在类前
@RunWith(PowerMockRunner.class)
@PrepareForTest(OrderTypeEnum.class)
//在@Before中添加枚举mock
@Before
public void beforeTest() {
mockStatic(OrderTypeEnum.class);
}
3.4 模拟依赖方法
在模拟完依赖的参数和返回值后,可以利用Mockito功能,进行依赖方法的模拟。如果模拟对象还有方法调用,则需要模拟这些依赖对象的方法。
/***
when.thenReturn 和 doReturn.when是两种实现方式
只有在使用@Spy时才会有区别
参考链接:https://www.imooc.com/wenda/detail/594190#id_653606
***/
//模拟枚举的方法调用
when(OrderTypeEnum.getByValue(anyInt())).thenReturn(100);
//模拟依赖对象的依赖方法调用
doReturn(resultInfoDTO).when(orderInfoService).getLastOrderInfo(orderInfoDTO);
3.5 模拟构造方法
PowerMock提供了对构造方法的模拟,但是需要把构造方法的类放在@PrepareForTest中
//必须在@PrepareForTest中添加对应类
@PrepareForTest({OrderTypeEnum.class, OrderServiceImpl.class})
whenNew(OrderInfoDTO.class).withNoArguments().thenReturn(orderInfoDTO);
3.6 验证方法调用次数
被测方法调用后,一些方法会出现调用多次或根据不同条件进行不同次数的调用。此时,可以根据验证方法调用次数,确定代码的有效性
verify(orderInfoService,times(1)).getLastOrderInfo(orderInfoDTO);
3.7 验证返回值
对于方法调用后的出参,我们会有一定的预期。所以,可以根据校验返回值是否符合预期,确保返回值的正确性
Assert.assertEquals(result, "123");
3.8 验证异常对象
JUnit的@Test注解提供了一个expected属性,可以指定一个期望的异常类型,用于捕获异常并验证其异常类型。【注】:只能验证异常类型,不能验证异常信息。
@Test(expected = BPLException.class)
4 单测举例
下面是一个本地方法的单元测试用例,方法中调用了外部接口,并且其中包含了枚举值的使用。
源方法即需要单测方法:

首先,是单元测试时一些必要的初始化:

4.1 单测场景一(确定接口调用,并返回值正确):
通过verify方法来确定接口是否调用过,并且只调用过1次。
通过assert来确认返回值是否满足预期

4.2 单测场景二(必要异常是否抛出):
通过在@Test注解上加入expected属性,测试当接口返回值为空时,是否可以抛出异常

4 总结
编写单元测试在开发中的地位举足轻重。在开发过程中,避免不了优化或重构历史代码。单元测试,在一定程度上可以帮助测试更新后逻辑,以及潜在调用链。另外也分享一些链接,希望可以帮助大家完成从0到1的搭建。
5 参考资料
- Java编程技巧之单元测试用例编写流程:https://mp.weixin.qq.com/s/hX_RIYs-nBnqVwdq5B4rhg
- powerMock的Git链接:https://github.com/powermock/powermock
- powerMock简介:https://www.baeldung.com/intro-to-powermock
- 避免Install的时候Skip test: https://maven.apache.org/plugins-archives/maven-surefire-plugin-2.12.4/examples/skipping-test.html
作者:京东物流 牟佳义
来源:京东云开发者社区 自猿其说Tech 转载请注明来源
Java单元测试及常用语句的更多相关文章
- Hbase/Hadoop Java API编程常用语句
从scanner获取rowkey: for(Result rr : scanner){ String key =Bytes.toString(rr.getRow())} HBase API - Res ...
- Java单元测试技术1
另外两篇关于介绍easemock的文章:EasyMock 使用方法与原理剖析,使用 EasyMock 更轻松地进行测试 摘要:本文针对当前业软开发现状,先分析了WEB开发的技术特点和单元测试要解决的问 ...
- Java单元测试(Junit+Mock+代码覆盖率)
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- Java单元测试框架 JUnit
Java单元测试框架 JUnit JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于KentBeck的sUnit的xUnit家族中为最成功的一 ...
- Java单元测试(Junit+Mock+代码覆盖率)---------转
Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测 ...
- 基于java平台的常用资源整理
这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...
- 这里整理了基于java平台的常用资源
这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...
- 转载-使用 Feed4JUnit 进行数据与代码分离的 Java 单元测试
JUnit 是被广泛应用的 Java 单元测试框架,但是它没有很好的提供参数化测试的支持,很多测试人员不得不把测试数据写在程序里或者通过其它方法实现数据与代码的分离,在后续的修改和维护上有诸多限制和不 ...
- Java单元测试工具:JUnit4(一)(二)(三)(四)
Java单元测试工具:JUnit4(一)--概述及简单例子 Java单元测试工具:JUnit4(二)--JUnit使用详解 Java单元测试工具:JUnit4(三)--JUnit详解之运行流程及常用注 ...
- java中最常用jar包的用途说明
java中最常用jar包的用途说明,适合初学者 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实 ...
随机推荐
- 我写了本开源书:《3D编程模式》
大家好,我写了本开源书,罗列了我从自己的实战项目中提炼出来的关于3D编程(主要包括"3D引擎/游戏引擎"."编辑器"开发)的各种编程模式 本书的在线阅读地址在这 ...
- 代码随想录算法训练营Day35 贪心算法
代码随想录算法训练营 代码随想录算法训练营Day35 贪心算法| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球 860.柠檬水找零 题目链接:860.柠檬水找零 在柠 ...
- javascript5 定时器功能
定时器功能: 定时器功能是window对象方法,涉及到 定时器和延时器,具体 看代码 定时器 timer=setInterval(function (){},300) 清除定时器: clearInte ...
- 【lwip】15-NETCONN接口
前言 终于到接口层了. 原文:李柱明博客:https://www.cnblogs.com/lizhuming/p/17442931.html 框架描述 前面我们已经学完了,都知道raw接口了,其实 ...
- 最小编译器和 UI 框架「GitHub 热点速览」
如果有一个关键词来概述本周的 GitHub 热门项目的话,大概就是 van 和 sectorc 都用到的 smallest.只不过一个是前端的响应式框架,一个是搞编译的 C 编译器.它们除了轻量化这个 ...
- 文档在线预览(三)使用js前端实现word、excel、pdf、ppt 在线预览
@ 目录 实现方案 一.docx文件实现前端预览 1.docx-preview 2.Mammoth 二.PDF文件实现前端预览 1.pdf.js 2.pdfobject.js 3.vue-pdf 4. ...
- 在asp.net core web api中添加efcore使用codefirst
首先创建webapi项目,我这里使用的版本是.net6 在nuget中添加对应的工具包 红框标出来的是对应的数据库扩展包,mysql用mysql版,sqlserver用sqlserver版,选择正确的 ...
- 基于 Linux 集群环境上 GPFS 的问题诊断
作者:谷珊,帅炜,陈志阳来源:IBM Developer GPFS 的概述 GPFS 是 IBM 公司提供的一个共享文件系统,它允许所有的集群节点可以并行访问整个文件系统.GPFS 允许客户共享文件, ...
- 从零开始整SpringBoot-搭建一个企业级项目
创建Springboot项目 在企业里的项目多数是分Modules的,更多是通过物理方式隔离层之间的职责. 首先按照原有新建SpringBoot项目创建,填好相关信息后,选择Java 8其他不用选. ...
- 2023-07-01:redis过期策略都有哪些?LRU 算法知道吗?
2023-07-01:redis过期策略都有哪些?LRU 算法知道吗? 答案2023-07-01: 缓存淘汰算法(过期策略) 当Redis的内存超出物理内存限制时,内存中的数据就会频繁地与磁盘进行交换 ...