在真实的测试当中,并不能所有的逻辑都可以自己控制,因此有了mock测试 。今天就结合场景来讲一下怎么做mock测试 。
适合对象:初次尝试集成和使用mockito进行单元测试的开发同学
文章插图
Mock框架的集成这里选择的是Mockito + PowerMockito 。为什么会集成PowerMockito,是因为有个想要mock的方法是static方法 。这个需要PowerMockito,假如都只是普通类,就可以不用了 。
集成关键点如下【Spring的Mock测试你用上了吗?】1、版本对应:这两个mockito的版本是有一个对应关系,假如不对应,会出现类找不到的情况 。比如 ClassNotFound org/mockito/mockitoframework。而网上也已经有对应关系如下链接
https://github.com/powermock/powermock/wiki/Mockito#supported-versions
这是我的集成版本
<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>2.28.2</version><scope>test</scope> </dependency> <dependency><groupId>org.powermock</groupId><artifactId>powermock-module-junit4</artifactId><version>2.0.2</version><scope>test</scope> </dependency> <dependency><groupId>org.powermock</groupId><artifactId>powermock-api-mockito2</artifactId><version>2.0.2</version><scope>test</scope> </dependency>
2、注解方式集成:因为使用spring boot的项目,所以考虑怎么用注解方式集成 。最后我的注解方案如下所示@RunWith(PowerMockRunner.class)@PrepareForTest({JdbcClient.class})@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)@PowerMockIgnore({"JAVAx.net.ssl.*","javax.management.*", "javax.security.*", "javax.crypto.*"})
这几个,都有自己的用处,分别说下:- @RunWith(PowerMockRunner.class) :假如要使用powermock,那就需要配置这个,不然powermock无法使用
- @PrepareForTest({JdbcClient.class}) :这里的列表,设定的是需要static mock 的类,我的测试场景中,需要mock JdbcClient的static query 方法
- @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class) : 一开始,只配置了前两个,然后发现从spring中inject注入的service都为空了 。原来要需要使用这个注解,这样就和spring test 组合上了
- @PowerMockIgnore({"javax.net.ssl.*","javax.management.*","javax.security.*","javax.crypto.*"}) :PowerMock大概是mock的太多了,所以假如没有这行注释,也是各种报错 。ClassCastException: class sun.security.provider.ConfigFile 这种 。
TIPS:这些注解可以写到一个abstract TestClass 上,后面的测试类继承这个就方便了Mock场景举例好,正式开始mock 。首先来讲,网上那些例子,好多都太简单了,不能当做实际场景 。比如mock ClassA.method1,然后直接验证method1的结果 。这种只能验证集成的对不对 。还是结合真实场景比较好 。
场景一:修改外部服务调用,比如调用支付宝支付,或者发个短信什么的,也可以是数据库查询
有时候,我们不希望真的去调用外部(比如配置太复杂,比如收费,比如想模拟错误结果) 。或者想自己控制数据库查询结果(或者遇到了我这边只有正式环境才有某个库的情况) 。那这时候,就需要使用Mock Service来解决 。
先撸代码,再分析 。
这个场景讲解mock的常规使用手法
以及在spring注入service情况下,如何处理mock
public class MockitoTest extends BaseTest {@AutowiredDemoService demoService;@MockRemoteService remoteService;@Testpublic void testHack() throws Exception {demoService.setRemoteService(remoteService);String result = "fail";Mockito.when(remoteService.sendRequest(any())).thenReturn(result);String callResult = demoService.callRemote("something");assertEquals("fail", callResult);Mockito.verify(remoteService).sendRequest(any());}}
这个场景感觉用的挺多的 。demoService是想要测试的功能,其中用到了remoteService.sendRequest的结果 。而又不想实际调用remoteService 。这时候就可以先把remoteService.sendRequest给mock掉,给出自己设定的返回结果 。这时候要注意的一个点是:remoteService并不归属springContext管理,所以run test 以后,会发现,这个mock毫无作用 。debug之下,可以看到注入和mock的remoteService并不是一个实例 。
那如何使remoteSerivce变成mockService,这里有两个思路 。
推荐阅读
- 2017年诺贝尔物理学奖的获得者 20年诺贝尔物理学奖揭晓
- 为什么要在月球上建造基地 月球建设基地的可能性
- 冥王星到底有多可怕?它被踢出行星行列,是有原因的 冥王星为什么被踢出行星
- 断尾重生的动物有哪些 什么动物断尾求生
- 被我用烂的DEBUG调试技巧,专治各种搜索不到的问题
- Linux分段系统中的地址映射和基本机制
- 编辑器的自制
- 设计一个高效的定时任务系统
- Pony - 最智能的 Python ORM 框架
- Java开源框架之SpringMVC原理及源码解析