本文系《pytest源码剖析》系列内容
15. monkeypatch
插件路径:_pytest.monkeypatch
实现的 hook
无
调用的 hook
无
定义的 fixture
monkeypatch
作用域:functions
返回值:MonkeyPatch实例对象
插件功能
创建猴子补丁类:MonkeyPatch,可以修改
对象属性
字典 item
当前目录
环境变量
syspath
创建 fixture:monkeypatch
用例结束后,自动还原修改
创建函数:resolve
从a.b.c格式的字符串加载对象
代码片段
@fixturedef monkeypatch() -> Generator["MonkeyPatch", None, None]: mpatch = MonkeyPatch() yield mpatch mpatch.undo()
class MonkeyPatch: @classmethod @contextmanager def context(cls) -> Generator["MonkeyPatch", None, None]: m = cls() try: yield m finally: m.undo()
fixturemonkeypatch基本说明了MonkeyPatch的用法
MonkeyPatch也支持上下文管理器方式直接使用
MonkeyPatch 用法示例
1. 简单的示例
import requestsfrom requests.sessions import Session
def test_mock(monkeypatch): # 使用fixture,有mock效果 def mock_request(*args, **kwargs): raise ValueError('禁止使用requests发送网络请求') monkeypatch.setattr(Session, 'request', mock_request) # 进行mock
requests.get('https://www.baidu.com')
def test_mock_undo(): # 在另一个用例中,不受mock影响 resp = requests.get('https://www.baidu.com') assert resp.status_code == 200
2. 常用的场景
class MockResponse: status_code = 444 text = 'sanmu'
def test_mock(monkeypatch): def mock_request(*args, **kwargs): return MockResponse() # 返回MockResponse,而不是发送真实的网络请求
monkeypatch.setattr(Session, 'request', mock_request)
resp = requests.get('https://www.baidu.com') assert resp.status_code == 444 assert resp.text == 'sanmu'
3. 其他用法
除了修改属性之外,还可以删除属性,使得对象在被使用时引发异常
不仅是对象的属性,以下类型都可以进行进行修改 / 删除:
字典
环境变量
syspath
cwd
其实展开来讲值得专门写一篇,欢迎关注后续更新
简评
此前看到一些在测试中需要 mock 的代码,使用了unittest中的mock,类似这样:
虽然【在一个测试框架中使用另一个框架的功能】有一种奇怪的违和感,
但是想到unittest是 python 标准库,这似乎又很合理
在这次源码剖析的过程中,居然终于通过源码找到了 pytest 自带的 mock 功能,
可以说意外之喜了,刚好可以消灭这奇怪又合理的违和感 :)
...
monkeypatch和mock有什么区别?
简单来说,mock 是目的,monkeypatch 是手段
pytest 和 unittest 在实现 mock 的方式上,其实都是属于 monkeypatch`
测试替身 (Test double) 是自动化测试中的术语,为了简化系统、降低复杂性,促成快速、稳定的测试活动。
常见的类型有:
mock:预设结果,并不真的做出访问动作
stub:预设结果,也做出访问动作
fake:做出访问动作,访问低成本替代品,而不是真实的高成本资源
mock 是相对简单、方便、灵活的一种方式,
比如在测试用例中需要调用某接口、某数据库,但是苦于此时网络无法连接,
那么通过对调用接口的代码(或调用数据库的代码)进行 mock,让其直接返回结果,
就可以继续进行下面步骤了。
注意:mock 让我们并没有真正连接网络,却得到结果,成本是最低的
在动态语言中,monkeypatch是非常方便的 mock 方式,其工作原理是:
在代码运行时,直接修改被 mock 对象,导致被 mock 对象的执行方式被改变
领取专属 10元无门槛券
私享最新 技术干货