前言
大家好,我是洋子。在文章《接口测试(3)- 构造测试数据》我提到了构造测试数据的方法,但这篇文章当中都是构造真实的测试数据。然而在实际测试过程中,我们难免会遇到业务场景非常复杂,上下游调用链路复杂或者是某个依赖模块不稳定等,导致无法构造真实测试数据的情况
这个时候想要进行测试,就需要先去进行Mock数据,然后再进行接下来的测试
Mock数据的含义
那么Mock数据是什么意思呢
首先Mock这个英文单词有模拟
的意思,模拟数据通俗的理解就是构造假数据
,即Mock数据就是通过构造假数据来达到测试的目的,它广泛运用于功能测试、接口测试、单元测试
- 在
功能测试
中,可以先Mock某页面调用接口的返回字段的值,使得页面获取到假数据,方便测试页面展示效果
- 在
接口测试
中,若接口A为服务A当中的接口,并依赖下游服务B,C,其中B服务及其不稳定,则可以Mock服务B中接口的返回数据,使得服务A能正常获取到假数据,进而能够正常测试接口A
有小伙伴可能有疑惑,接口
和服务
这两者有什么区别,一个服务里面一般是含有一个或多个接口,一般情况下,服务A只依赖服务B里面的某一个或几个接口,但如果服务B不稳定,就会导致整体服务B不可用,因此服务A无法正常返回数据,进而无法正常测试接口A
这种情况下可以单独Mock 服务A 依赖 服务B的接口,也可以创建一个完整的 Mock 服务B,如果是搭建完整的Mock服务,难度还比较大,主要体现在下面两个方面
(1)需要对该服务B非常了解,因为我们测试当中一般是对被测服务A了解,但下游服务B因为不是我们的被测对象,往往不清楚它的调用逻辑
(2)需要根据服务A的传参,调用Mock 服务B,返回动态的结果。比如没有传参或参数不对,Mock 服务B就不能再返回正确的结果
为了解决上面两大难题,我们往往是需要进行契约测试
,引入契约文件,记录服务B的请求和返回信息,由于契约测试内容非常多,本文暂不进行展开
- 在
单元测试
中,可以Mock 整个类或者是某个类当中的某个方法
在单元测试中Mock数据一般有两种运用场景
- 第一个场景是被测试对象依赖的对象构造复杂。比如:Class A 依赖 class B、class B 依赖 class C,此处我们想测试classA,在没有mock的情况下就要去根据要求去构造classB、classC对象,耗时耗力。在Mock的情况下,我们可以直接Mock classB、C并通过设计其行为来实现测试classA的目的,因为我们只是想测试class A的行为是否符合预期,我们并不需要测试依赖的对象
- 第二个场景是被测方法依赖的方法还未开发完成。即被测试方法所依赖的模块还没有开发完成,而被测试对象需要需要依赖模块的返回值进行测试。也就是测试方法依赖了无法获取的下游数据。比如:service中方法的测试需要dao中的访问数据库操作并获取其返回值,但是我们还没有开发完成对应的dao方法,我们就可以mock一个dao层的对象,将其行为设置为:当调用其中的某个方法时返回一个设好的固定值。这样我们对service的测试就可以不必受dao层的开发速度影响。也符合只对service方法逻辑进行测试
除了我们测试工程师需要Mock数据外,在整个需求开发初期,后端开发一般会给前端开发提供API接口文档,前端开发时常也会根据接口文档进行Mock接口的返回数据用于辅助开发前端页面
为什么前端开发也要Mock数据呢?这是因为在开发阶段,往往前后端的开发是并行
的,这个时候由于后端还在正常开发当中,无法提供真实的API服务给前端调用,前端则根据接口文档当中的接口定义(请求方式、请求参数、接口预期返回数据),先进行Mock后端接口,帮助完成自己的前端部分的开发工作
直到后端开发完毕后,前端再使用开发环境里真实API服务进行联调测试,联调通过后提测给测试
Mock数据的层级关系
根据上面在单元测试、功能测试、接口测试的Mock数据的场景,我们可以看出Mock数据的层级关系
方法级
mock:mock的对象是一个函数(方法)调用类级
mock:mock的对象是一个类接口级
mock:mock的对象是一个API接口服务级
mock:mock的对象是整个服务
在功能测试阶段,一般是接口级Mock。在单元测试阶段,则为方法级和类级Mock。在接口测试阶段,一般则为接口级Mock或者服务级Mock
Mock数据的工具与方法
下面结合功能测试、接口测试、单元测试
这三种测试场景,讲解一下对应Mock数据的工具和方法
功能测试
在做功能测试时,可使用Charles的Map Local
功能进行Mock数据,具体使用方法如下,先抓包获取到接口信息,可以看到其中有个ttl
字段,值为1
右键菜单保存该接口响应结果,到指定的路径下
然后找到刚刚保存的响应结果文件,一般为Json格式,修改其中的ttl为2,以达到Mock数据的目的,修改后保存文件
找到Charles顶部菜单栏Tools
-Map Local
功能
进入后勾选Enable Map Local
打开Map Local的开关,然后点击Add,填入Map From的URL信息(可以通过右键菜单Copy URL)
最后选择本地Map To 的文件,这个文件就是我们刚刚修改的响应结果文件
设置完毕后,点击OK即可。最后,我们验证一下效果,再次访问刚才的URL,通过抓包可以发现ttl字段的值已经变成2了
大家可以根据需要,利用这种方法去Mock 其他HTTP协议接口的返回数据,Charles更多功能可以查看《Charles从入门到精通》这篇文章
如果使用的是Fiddler
抓包工具,可以利用AutoResponder
功能实现mock测试
接口测试
在接口测试中,能用来Mock数据的工具就太多了,下面列举一些常用工具
(1)Postman
提供的Mock Servers
功能,Yapi
平台的数据Mock功能
(2)json-server
,用于模拟服务端接口数据的工具,可以根据json数据建立一个完整的web服务
(3)Mock.js
,在前端开发当中,若前端使用的Vue
框架,则可以用Mock.js
去Mock接口数据
(4)moco
框架,在开发 Mock 服务的时候,它提供了一种不需要任何编程语言的方式,你可以通过撰写它约束的 Json 建立服务,并通过命令启动对应的服务,这就可以快速开发和启动运行你需要的 Mock 服务
单元测试
在单元测试当中,各种编程语言一般都提供了用来帮助单元测试的Mock框架
- Java 的
Mockito
、JMockit
、PowerMock
等 - Python的
mock
模块是 Python 的测试框架unittest
下的一个子包,是单元测试的一个重要模块 - Go语言,则可以使用
Monkey Patch
这个特性去Mock数据,Monkey库
是Monkey Patch
的一个 Go 版本实现
结束语
本文给大家介绍了Mock数据的含义、工具和方法,内容有点多,大家慢慢消化
本来想继续写一下单元测试当中Mock框架的具体用法,一看都2000多字了,那就留到下次吧(其实是我懒)