python - mock 处理
前言
在现在的软件开发过程中,特别是app的部分,需要的很多数据以及内容,都是来自server端的API,但是不能保证在客户端开发的时候,
api在server端已经开发完成,专门等着前端来调用,理想的情况是前端在开发的时候,已经有人写好了接口,直接调用就可以了。
但往往是页面写好了,后端接口没有写好,这时前端等后端的话就会比较浪费时间。
mock的作用
- 单元测试,函数A的参数需要函数B的返回,但是函数B原先已经测试过了,就不要重新再测试了,这时就可以用mock模块来模拟函数B的返回。
- 依赖第三方接口的测试,比如说获取身份信息,支付等第三方接口,做自动化测试或者性能测试的时候就可以利用mock来模拟第三方接口的返回。
- 前后端联调,前端开发写页面比较快,这时就可以通过mock来模拟后端接口的情况,就不需要等后端把接口写好再来联调了。
先举一个例子
通过 return_value 参数在构造函数中设置返回值,看官方的例子:
import unittest
from unittest import mock
def add(a, b):
"""两个数相加的功能"""
pass # 还没有时间开发这个功能,占个坑
# 测试 add
class TestAdd(unittest.TestCase):
def test_add(self):
"""
www = mock.Mock(return_value=8) # 构造mock 返回 8
print(type(www)) # <class 'unittest.mock.Mock'>, 类对象
result = www(4, 4, 4) # 这里无论怎么写,result的值都是 8 ,所以 www(4, 4) 这里就可以随便构造函数了
self.assertEqual(result, 8) # 断言,判断两个值相等
"""
add = mock.Mock(return_value=8)
result = add(4, 4) # 构造函数 add 的格式
self.assertEqual(result, 8)
if __name__ == '__main__':
unittest.main()
如果开发把功能开发好了,那怎么处理了呢,很简单,传一个 side_effect 关键字参数即可。改一下代码
import unittest
from unittest import mock
def add(a, b):
"""两个数相加的功能"""
return a + b # 开发把两个数相加的功能开发好了
# 测试 add
class TestAdd(unittest.TestCase):
def test_add(self):
"""
www = mock.Mock(return_value=8) # 构造mock 返回 8
print(type(www)) # <class 'unittest.mock.Mock'>, 类对象
result = www(4, 4, 4) # 这里无论怎么写,result的值都是 8 ,所以 www(4, 4) 这里就可以随便构造函数了
self.assertEqual(result, 8) # 断言,判断两个值相等
"""
testAdd = mock.Mock(return_value=8, side_effect=add) # 传side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试
result = testAdd(4, 4) # 这里调的就是上面 add 的方法了,只能传入两个参数,可以改来试试
self.assertEqual(result, 8)
if __name__ == '__main__':
unittest.main()
用户-商户-第三方支付的业务流程
假设一个场景:
支付模块,开发没有跟第三方平台对接好支付接口,或者你跑自动化脚本的时候不想每次都真实支付。
平时的功能测试可以真实支付,测试完成后,去找财务报销即可。我们做自动化测试的时候就可以使用mock功能来模拟第三方的返回。
你可以根据接口文档的规定,把接口的地址和入参传过去,然后自己mock接口的不同返回界面。
第三方支付的接口是这样子:
模拟第三方支付接口的返回
# pay.py
import requests
class PayApi(object):
def zhifubao(self, out_trade_no, total_amount, subject, store_id, timeout_express):
"""第三方支付的接口,比如支付宝,微信等"""
pay_url = "http://www.pay.com" # 第三方支付接口地址
data = {
"out_trade_no": out_trade_no,
"total_amount": total_amount,
"subject": subject,
"store_id": store_id,
"timeout_express": timeout_express
}
response = requests.post(pay_url, json=data) # 请求第三方支付接口
return response # 返回状态码
def pay(self, user_id, out_trade_no, total_amount, subject, store_id, timeout_express):
"""自己项目的接口"""
# 调用第三方支付接口
response = self.zhifubao(out_trade_no, total_amount, subject, store_id, timeout_express)
try:
if response['status_code'] == '200':
return '支付成功'
elif response['status_code'] == '201':
return '支付失败,余额不足'
else:
return '未知错误'
except Exception:
return "Error, 服务器异常,请重试!"
if __name__ == '__main__':
pass
以上第三方接口是模拟的,不能真正运行,通过mock来模拟,以下编写测试用例
# test_pay.py
import unittest
from unittest import mock
from pay import PayApi
class TestPayApi(unittest.TestCase):
def test_success(self):
pay = PayApi()
pay.zhifubao = mock.Mock(return_value={'status_code': '200'}) # {'status_code': '200'}返回给 zhifubao
status = pay.pay("001", "2021120921", "1999", "pay002", "dev100", "121")
self.assertEqual(status, '支付成功')
def test_fail(self):
pay = PayApi()
pay.zhifubao = mock.Mock(return_value={'status_code': '201'})
status = pay.pay("002", "2021120921", "1998", "pay003", "dev101", "60")
self.assertEqual(status, '支付失败,余额不足')
if __name__ == '__main__':
unittest.main()
上面这个就是使用mock对象的基本使用,在上面的例子中我们替换了自己写的模块的对象,其实也可以替换标准库和第三方模块的对象。
分解线-------------------
人类的幸福并不相通,但是痛苦确是一样的;
选择了容易,往往快乐是一时的,代价却是持续的。
分类:
python
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现