作者:京东物流 杨建民

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
  1. import X;
  2. import org.junit.Test;
  3. import org.junit.runner.RunWith;
  4. import org.mockito.InjectMocks;
  5. import org.mockito.MockitoAnnotations;
  6. import org.powermock.api.mockito.PowerMockito;
  7. import org.powermock.core.classloader.annotations.PowerMockIgnore;
  8. import org.powermock.core.classloader.annotations.PrepareForTest;
  9. import org.powermock.modules.junit4.PowerMockRunner;
  10. /**
  11. * 测试类A,调用服务B和一个静态工具类X
  12. */
  13. @RunWith(PowerMockRunner.class)
  14. @SpringBootTest(classes = {
  15. A.class
  16. })
  17. @PowerMockIgnore({"javax.management.*"})
  18. @PrepareForTest({X.class}) //mock 静态方法
  19. public class ATest {
  20. @InjectMocks
  21. private A a;
  22. @Mock
  23. private B b;
  24. @Before
  25. public void setUp() throws Exception {
  26. MockitoAnnotations.initMocks(this);
  27. }
  28. @Test
  29. public void Test() {
  30. when(b.someMethodB(any())).thenReturn(someThingB());
  31. a.someMethodA(someThingA1(), someThingA2());
  32. verify(b).someMethodB(any());
  33. }
  34. /**
  35. * 异常边界测试
  36. */
  37. @Test
  38. public void test_ExceptionTest() throws ParseException {
  39. PowerMockito.mockStatic(X.class);
  40. // 模拟异常抛出的场景
  41. when(X.strToDate(anyString(), anyString())).thenThrow(ParseException.class);
  42. when(X.convertLocalDateTime(any())).thenReturn(someThing());
  43. when(b.someMethodB(any())).thenReturn(someThingB());
  44. a.someThingA(someThingA1(), someThingA2());
  45. verify(b).someMethodB(any());
  46. }

​优雅的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等,但上述技术依然适用于大型系统质量内建,读者可根据自身情况选择性选用。​

一文教会你mock(Mockito和PowerMock双剑合璧)的更多相关文章

  1. 使用MRUnit,Mockito和PowerMock进行Hadoop MapReduce作业的单元测试

    0.preliminary 环境搭建 Setup development environment Download the latest version of MRUnit jar from Apac ...

  2. 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用

    转 单元测试及框架简介 --junit.jmock.mockito.powermock的简单使用 2013年08月28日 14:33:06 luvinahlc 阅读数:6413 标签: 测试工具单元测 ...

  3. springboot集成mockito与powermock

      mockito大家都比较熟悉了,存在或者不存在,都不要紧,mockito让你有一种只要一出手,就知道有没有的感觉.但是它也不是万能的,比如静态方法.私有方法,它就无能为力了.这是为什么呢?当然不是 ...

  4. Mock之easymock, powermock, and mockito

    easymock, powermock, and mockito Easymock Class Mocking Limitations To be coherent with interface mo ...

  5. Spring Boot(九)Swagger2自动生成接口文档和Mock模拟数据

    一.简介 在当下这个前后端分离的技术趋势下,前端工程师过度依赖后端工程师的接口和数据,给开发带来了两大问题: 问题一.后端接口查看难:要怎么调用?参数怎么传递?有几个参数?参数都代表什么含义? 问题二 ...

  6. Mock利器:PowerMock

    powerMock不仅支持接口mock,final类.静态类.静态方法.私有方法都支持mock,还是很强大的: 1.gradle引用: myonlycompile('org.powermock:pow ...

  7. Mockito 库、powermock扩展

    转载:http://blog.csdn.net/kittyboy0001/article/details/18709685 Mockito 简介 Mockito 是目前 java 单测中使用比较流行的 ...

  8. 用maven搭建 testNG+PowerMock+Mockito测试框架

    单元测试是开发中必不可少的一部分,是产品代码的重要保证. Junit和testNG是当前最流行的测试框架,Junit是使用最广泛的测试框架,有兴趣的话自己baidu一下. testNG基于Junit和 ...

  9. mockito中两种部分mock的实现,spy、callRealMethod

    什么是类的部分mock(partial mock)?A:部分mock是说一个类的方法有些是实际调用,有些是使用mockito的stubbing(桩实现). 为什么需要部分mock? A:当需要测试一个 ...

  10. Mockito文档-单元测试技术

    Overview  Package   Class  Use  Tree  Deprecated  Index  Help     PREV CLASS   NEXT CLASS FRAMES     ...

随机推荐

  1. 任务清单小功能的实现(任务的增、删、改、查、存储)使用Vue实现

    文章目录 1.实现的效果(视频演示) 2.重点讲解(编辑的实现) 2.1 提示(官网介绍nextTick的用法) 3.编辑功能的核心代码 4.完整的代码 5.以往练习 任务清单案例(纯Vue) 实现的 ...

  2. 制作一个windows垃圾清理小程序

    制作一个windows垃圾清理小程序: 把下列代码保存为.bat文件(如垃圾清理.bat) 双击它就能很快地清理垃圾文件,大约一分钟不到. 就是下面的文字(这行不用复制)=============== ...

  3. DevOps | 如何快速提升团队软件开发成熟度,快速提升研发效能?

    今天一个小伙伴问我,如何「快速提升」一个团队的软件开发成熟度?我犯难了.我个人理解一个团队的软件开发成熟度涉及的东西很多,但最简单最直接的方法就是发钱涨工资,可是估计很多公司不愿意,那就只有扣了. 快 ...

  4. 空链接的作用以及<a href="#"></a>和<a href="javascript:;"></a>的区别

    空链接的作用以及<a href="#"></a>和<a href="javascript:;"></a>的区别在 ...

  5. 栈溢出漏洞利用流程——以syncbrs为例

    0x1 缓冲区溢出漏洞攻击简介 缓冲区溢出攻击是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序的堆栈,使程序转而执行其他指令,以达到攻击 ...

  6. java代码整洁之道

    package Day01;import org.junit.Test;import java.text.NumberFormat;import java.util.Scanner;public cl ...

  7. 深入学习SpringBoot

    1. 快速上手SpringBoot 1.1 SpringBoot入门程序开发 SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程 1. ...

  8. Springboot实现验证码登录

    Springboot实现验证码登录 1.背景 本人近期正在完成毕业设计(旅游信息管理系统)的制作,采用的SpringBoot+Thymeleaf的模式.在登录网站时想要添加验证码验证,通过网上查找资料 ...

  9. 质数之和【计算第x个到第y个质数之和】

    题目:质数之和 已知,第一个质数是2,第二个质数是3,第三个质数是5,第四个质数是7,第五个质数是11,第六个质数是13,第七个质数是17,输入两个不相等的正整数a和b,求出第a个质数到第b个质数当中 ...

  10. nginx的域名重写和转发案例

    对url进行重写 location = /tongyong_OTA_1.0.3.bin { rewrite ^(.*)$ http://36.133.87.223/lecode-server/leco ...