01为什么要用Mock
服务端与客户端约定了接口,但服务端还没有完成开发时,客户端一般由如下处理方式:
1、在程序中写模拟数据
-
程序中增加垃圾代码,后期还要删除,可能对代码造成影响
-
模拟异步请求不方便
-
服务端接口开发完成后,需要重新书写网络请求部分的代码
-
JS、iOS、Android 多前端需要分别模拟数据,重复工作量
2、使用 Nginx、http-server 等 WebServer
-
只支持 GET 请求
-
无法针对请求进行校验或特定处理
3、自己写简单的程序模拟返回数据
-
开发期间 API 还处于频繁变动时期,持续调整成本较高
以上方法均不方便做单元测试
对于需要演示的场景,没有后端业务服务器支撑,无法演示,客户端改造成本高
所以要引入Mock技术
02Mock使用场景
在使用Mock的过程中,发现Mock是有一些通用性的,对于一些应用场景,是非常适合使用Mock的:
1)真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)
2)真实对象很难被创建(比如具体的web容器)
3)真实对象的某些行为很难触发(比如网络错误)
4)真实情况令程序的运行速度很慢
5)真实对象有用户界面
6)测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)
7)真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题)
当然,也有一些不得不Mock的场景:
8)一些比较难构造的Object:这类Object通常有很多依赖,在单元试中构造出这样类通常花费的成本太大;
9)执行操作的时间较长Object:有一些Object的操作费时,而被测对象依赖于这一个操作的执行结果,例如大文件写操作,数据的更新等等,出于测试的需求,通常将这类操作进行Mock;
10)异常逻辑:一些异常的逻辑往往在正常测试中是很难触发的,通过Mock可以人为的控制触发异常逻辑;
11)在一些压力测试的场景下,也不得不使用Mock,例如在分布式系统测试中,通常需要测试一些单点(如namenode,jobtracker)在压力场景下的工作是否正常。而通常测试集群在正常逻辑下无法提供足够的压力(主要原因是受限于机器数量),这时候就需要应用Mock去满足;
12)在mock点的选择过程中,以下的一些点会是一些不错的选择 网络交互:如果两个被测模块之间是通过网络进行交互的,那么对于网络交互进行Mock通常是比较合适的,如RPC;
13)外部资源:比如文件系统、数据源,如果被测对象对此类外部资源依赖性非常强,而其行为的不可预测性很可能导致测试的随机失败,此类的外部资源也适合进行Mock;
14)UI:因为UI很多时候都是用户行为触发事件,系统本身只是对这些触发事件进行相应,对这类UI做Mock,往往能够实现很好的收益,很多基于关键字驱动的框架都是基于UI进行Mock;
15)第三方API:当接口属于使用者,通过Mock该接口来确定测试使用者与接口的交互。
当然如何做Mock一定是与被系统的特性精密关联的,一些强制性的约束和规范是不合适的。
03Mock工具的选择
Mock测试工具分为单元测试级别的Mock工具和接口测试级别的Mock工具。
一、单元测试级别的Mock工具
目前,这个级别的Mock工具有easymock、jMock、Mockito、Unitils Mock、PowerMock、JMockit等等。
就目前来讲,是mockit+PowerMock、JMockit这两种工具使用人数较多。JMockit的功能最为完善,mockit+PowerMock的用户体验相对较好一点。
二、接口测试级别的Mock工具
接口级别的Mock工具完成的主要功能是对一个用户的请求,模拟server返回一个接口的响应数据。
目前,这类的主