Mock测试
Mock 就是在测试过程中,对于一些不容易构造/获取的对象,创建一个 Mock对象
来模拟对象的行为
Mock 方法
是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开。
Mock测试的作用
在单元测试过程中,数据可能需要经过多方获取,且流程复杂
Class A
要从 Class B
和Class C
中获取数据,而 Class C
中该数据又来源于 Class D
和 Class E
这时可以利用 Mock 去构造虚拟的Class B
和Class C
对象用于Class A
的测试,因为我们只是想测试class A的行为是否符合预期,并不需要去测试依赖对象
Mock 功能可以根据接口/数据结构定义
、Mock规则配置
、Mock 期望配置
,自动生成模拟数据,且使用者可以根据需要灵活构造各种结构的接口数据。
在项目迭代流程中,可能会遇到,前端人员已完成开发任务,而后端人员开发打接口尚未完成。
这种情况,可以通过postman、Apifox等测试工具搭建一个Mock服务,与前端人员联调先进行Mock测试,测试前端的一些内容,这样,在后端接口写好后提交到测试环境进行测试时,也会减少一些前端上的bug。
不过一般情况下,前端人员会自己通过Mock测试校验自己的代码,不需要测试人员进行Mock测试。
在做接口测试的时候,如果调用第三方系统的接口,而第三方系统没有提供测试环境,就需要测试人员使用Mock技术,通过Mock服务,自己造一个模拟的假接口,根据接口文档,预先设定各种请求返回的内容,这样在测试流程中,就不会因为某个接口不通,而影响整个业务流程的测试。
Mock测试的优点
- 团队并行工作
开发过程中,只要交互双方定义好接口,团队之间可以并行工作,进程互不影响,不需互相等待对方进度,只需约定好相互之间的数据规范(接口文档),即可使用 mock 构建出可用接口,然后尽快进行开发和自测,提前发现缺陷 - 测试驱动开发 TDD (Test-Driven Development)
单元测试是 TDD 实现的基石,而 TDD 经常会碰到协同模块尚未开发完成的情况,但有了 mock,测试人员可提前接入测试,提供测试效率,当接口定义好后,测试人员就可以创建一个 Mock,把接口添加到自动化测试环境,提前创建测试。 - 测试覆盖率
接口涉及入参,或者业务逻辑复杂的情况,某些场景无法通过正常手段进行操作,而通过mock虚拟模拟,可以有效的增加覆盖率 - 隔离系统
若一个接口在不同的状态下要返回不同的值,常见做法是复现这种状态然后再去请求接口,但使用某些接口时,可能因操作时机或方式不当导致失败,甚至污染后端存储如数据库等, 为避免系统数据库被污染,可以将接口调整为 Mock 模式,以保证数据库纯净。
Mock测试的缺点
Mock也不是万能的,使用Mock也存在着风险,需要根据项目实际情况和具体需要来确定是否选用Mock。
测试过程中如果大量使用Mock,mock测试的场景失去了真实性,可能会导致在后续的系统性测试时才发现bug,使得缺陷发现的较晚,可能会造成后续修复成本更大
Mock客户端
接口文档已对接完成,但后端接口还未开发完成,测试人员需要进行单元测试,或提前进行接口自动化测试,需要使用Mock各种请求返回的内容,可以使用Python中的Mock库
测试Python中的Mock库
安装
pip install Mock
Mock的使用
import unittest
from mock import Mock
def VerifyPhone():
'''
校验用户手机号
'''
pass
class TestVerifyPhone(unittest.TestCase):
def test_verify_phone(self):
data = {"code": "0000","msg": {"result": "success","phoneinfo": "移动用户"}}
VerifyPhone = Mock(return_value =data)
self.assertEqual("success",VerifyPhone()["msg"]["result"])
假设,有一个校验用户手机号功能(VerifyPhone
),还没有完成,但这时候需要提前进行测试,通过解耦温迪,我们知道这个功能的作用,以及接口会返回的情况
手机号校验通过
{
"code": "0000",
"msg": {
"result": "success",
"phoneinfo": "移动用户"
}
}
手机号格式错误
{
"code": "0002",
"msg": {
"result": "false",
"phoneinfo": "手机号格式错误"
}
}
手机号已存在
{
"code": "0003",
"msg": {
"result": "false",
"phoneinfo": "手机号已存在"
}
}
但是很显然,现在这个功能还不能用,所以通过Mock(return_value =data)
,将Mock的结果(相当于接口会返回的内容),赋予变量VerifyPhone
,此时断言中VerifyPhone()["msg"]["result"]
的结果,就是"success"
,断言通过。
当功能开发完成(接口开发完成),去掉VerifyPhone = Mock(return_value =data)
这行代码即可。这样,既达到了提前测试的作用,又不会发生太大的修改,节省了成本
Mock服务端
遇到前端人员已完成开发任务,而后端人员开发打接口尚未完成这种情况,需要和前端人员联调进行测试,则需要搭建Mock服务
方法有很多,比如通过通过postman、Apifox等测试工具搭建一个Mock服务,Mock一个接口进行测试。可参考该篇文章使用Postman进行Mock测试
推荐使用Apifox进行Mock接口测试,Apifox的Mock功能比较强大,Apifox官方文档写得很详细,这里就不举例了