一文教会你mock(Mockito和PowerMock双剑合璧)
作者:京东物流 杨建民
1.什么是Mock
Mock有模仿、伪造的含义。Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。mock工具使用范畴:
- 真实对象具有不确定的行为,产生不可预测的效果。
- 真实对象很难被创建。
- 真实对象的某些行为很难被触发。
- 真实对象实际上还不存在。
MockIto和PowerMock是众多Mock框架中的两种,类似的还有:JMock,EasyMock,大多 Java Mock 库如 EasyMock 或 JMock 都是 expect-run-verify (期望-运行-验证)方式,而 Mockito 则使用更简单,更直观的方法:在执行后的互动中提问。使用 Mockito,你可以验证任何你想要的。而那些使用 expect-run-verify 方式的库,你常常被迫查看无关的交互。非 expect-run-verify 方式 也意味着,Mockito无需准备昂贵的前期启动。他们的目标是透明的,让开发人员专注于测试选定的行为。
2.解决的问题
我们在写单元测试时,总会遇到类似这些问题:
1. 构造的入参,对于极值、异常边界场景不好复现,相关的逻辑测不到,只能依靠测试环境或预发跑,运气不好可能要改好几次代码重启机器验证,费时费力;
2. 依赖别人接口,可能需要别人协助测试环境数据库插数才能跑通;
3. 依赖的别人的接口还没有开发完,为了不影响提测,如何完成单元测试?
4. 编写的单元测试依赖测试数据库的数据,每次跑都要数据库改数?
5. 对service层加了逻辑,跑单元测试本地验证的时候,由于种种原因,本地环境跑不起来,折腾半天跑起来验证完了,下次开发需求又遇到了另一个问题本地环境启动报错???
6. 我就想dubug到某一行代码,但是逻辑复杂,东拼西凑的参数就是走不到,自己看代码逻辑还要去问别人接口的返回值逻辑??(未完待续……)引入Mockito和PowerMock使得编写单元测试更轻松,更省时,更省力。
3.如何解决问题
3.1 使用mock的意义
简单说就是无论谁的本地环境,无论判断条件多么苛刻,无论本地数据库的测试数据被谁删了改了,无论别人接口的返回值逻辑多复杂,无论自己代码逻辑多复杂,都能独立的、可重复执行的、行级别覆盖的单元测试用例。
3.2 Mockito和PowerMock
一句话说Mockito和PowerMock。当所测逻辑里有静态工具类方法或私有方法我们希望他返回特定值时(极值边界、异常测试场景),我们要用到PowerMock去弥补Mockito的不足,除此之外,用Mockito去写单测能完成我们日常任务95%的场景。
3.3 使用Mcokito和PowerMock的最佳实践
3.3.1 引入pom文件
3.3.2 Mockito和PowerMock 两条通用语法
打桩:
when(XXxService.xxMethod("期望入参")).thenReturn("期望出参"); 验证:verify(XXxService).xxMethod("期望入参");
4.举例说明
4.1 SpringBoot项目下Mockito和PowerMock最佳实践
- classes: 指定要加载的类
- properties: 指定要设置属性
- @InjectMocks: 需要注入mock对象的Bean
- @MockBean或@Mock: 需要mock的Bean
import X; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.MockitoAnnotations; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; /** * 测试类A,调用服务B和一个静态工具类X */ @RunWith(PowerMockRunner.class) @SpringBootTest(classes = { A.class }) @PowerMockIgnore({"javax.management.*"}) @PrepareForTest({X.class}) //mock 静态方法 public class ATest { @InjectMocks private A a; @Mock private B b; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } @Test public void Test() { when(b.someMethodB(any())).thenReturn(someThingB()); a.someMethodA(someThingA1(), someThingA2()); verify(b).someMethodB(any()); } /** * 异常边界测试 */ @Test public void test_ExceptionTest() throws ParseException { PowerMockito.mockStatic(X.class); // 模拟异常抛出的场景 when(X.strToDate(anyString(), anyString())).thenThrow(ParseException.class); when(X.convertLocalDateTime(any())).thenReturn(someThing()); when(b.someMethodB(any())).thenReturn(someThingB()); a.someThingA(someThingA1(), someThingA2()); verify(b).someMethodB(any()); }
优雅的mock可以考虑@spy,当然,mockito还有一些特性可以自行学习如:
5.遇到的一些问题及解决
- 打桩逻辑判断是通过equals方法判断的
- 测试的预期是抛出异常直接在注解上加:@Test(expected=BusException.class)
- 模拟的参数为null:Mockito.isNull()
- PowerMock mock静态和私有final会有一些格式区别
- PowerMockmock静态方法时也可以使用spy的方式使代码更优雅
- mock中发现,mock没有生效,可以尝试升级Mockito版本解决,另外与junit反射工具类结合使用,效果更佳。
- 涉及多层嵌套的使用场景,读者先思考”单元“选取是否合理,多层嵌套场景将@InjectMocks和@Spy(或@Mock)联合使用即可
结束语:
文章写于早些时候,目前有些较新技术涌入,如:Spock、TestableMock等,但上述技术依然适用于大型系统质量内建,读者可根据自身情况选择性选用。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
解读重要功能特性:新手入门 Apache SeaTunnel CDC
引言 点亮 ⭐️ Star · 照亮开源之路 https://github.com/apache/incubator-seatunnel 为什么说 CDC 是SeaTunnel平台中的一个重要功能特性?今天这篇文章跟大家分享一下 CDC 是什么?目前市面上的 CDC 工具现有的痛点有哪些?SeaTunnel面对这些痛点设计的架构目标是什么?另外包括社区的展望和目前在做的一些事情。 总体来说,市面上已经有这么多 CDC 工具了,我们为什么还要重复去造一个轮子? 带着这个疑问,我先给大家简要介绍下 CDC 是什么! CDC 的全称是 Change Data Capture,它就是一个数据变更捕获。变更数据捕获 (CDC) 使用 Server 代理来记录应用于表的插入、更新和删除活动。 这样,就可以按易于使用的关系格式提供这些更改的详细信息。 将为修改的行捕获列信息以及将更改应用于目标环境所需的元数据,并将其存储在镜像所跟踪源表的列结构的更改表中。 CDC的使用场景 异构数据库之间的数据同步或备份 / 建立数据分析计算平台 在 MySQL,PostgreSQL,MongoDB 等等数据库之间...
- 下一篇
贴吧低代码高性能规则引擎设计
作者 | 贴吧UEG技术组 导读 本文首先介绍了规则引擎的使用场景,引出贴吧规则引擎。从组件、变量、规则、处置四个模块介绍了规则引擎的组成部分,同时对最终规则文件的编译过程做了详细介绍。为了做到低代码,在规则配置上做到平台化,非研发同学即可完成。增加新的变量也只需要在变量平台进行简单操作,无需额外的代码提交。另外框架层面支持并行和异步的封装,在服务调用上也尽量做到减少代码,提高研发同学的效率。最后文章对贴吧规则引擎做了总结,也提供了一些常见的使用场景和思路。 全文6951字,预计阅读时间18分钟。 01 背景 百度贴吧是一个拥有10多年历史的UGC产品,在业务迭代中难免会有很多业务逻辑的代码,其中一部分业务逻辑用if-else等硬编码的形式开发,一部分引入了配置文件,通过配置文件的规则去执行不同的业务逻辑。在某些运营活动或权益规则中,需要频繁增加或者更改一些规则,这部分规则经常变动的部分就需要规则引擎来统一管理。 规则引擎是一种专注于业务规则的服务,它可以将业务规则从代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业务规则。规则引擎通过接受输入的数据,进行业务规则的评估,并...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能