pytest-mock提供预配置的mocker fixture,自动注入并管理生命周期,无需手动import或patch;正确用法是直接将mocker作为测试函数参数,如def test_xxx(mocker),并patch“被使用处”而非“定义处”,例如mock.patch('api.requests.get')而非'requests.get'。

pytest-mock 的 mock fixture 怎么用?
直接用 mock fixture,不用手动 import 或 patch —— pytest-mock 会自动注入一个预配置好的 Mock 实例(实际是 pytest_mock.plugin.MockerFixture),它比原生 unittest.mock 更轻量、作用域更清晰。
常见错误:写 from unittest.mock import patch 然后在测试函数里手动 @patch,结果和 pytest-mock 混用导致 patch 生效范围错乱、重复 patch 或未生效。
- 正确做法:函数参数直接加
mock,例如def test_fetch_user(mock) - 它等价于调用
mock.patch,但自动管理生命周期,测试结束自动 stop - 不支持直接 mock 内置函数(如
open、print),需用mock.patch显式指定目标
如何 mock HTTP 请求(比如 requests.get)?
别 mock requests.get 本身,而是 mock 调用它的模块里的引用 —— 这是 patch 的核心原则:patch「被使用的地方」,不是「定义的地方」。
假设你有 api.py:
import requests
def fetch_data(url):
return requests.get(url).json()
而测试写在 test_api.py 中,那么要 patch 的是 api.requests,不是 requests 全局:
- ✅ 正确:
mock.patch('api.requests')或mock.patch('api.requests.get') - ❌ 错误:
mock.patch('requests.get')(除非你在测试文件里直接 import requests 并调用) - 返回值设置用
return_value(同步)或return_value.json.return_value模拟链式调用
mock 返回异步响应(aiohttp / httpx)要注意什么?
pytest-mock 本身不处理协程,mock 对象默认不 awaitable。如果被测函数是 async,且调用了 aiohttp.ClientSession.get 这类协程方法,直接设 return_value 会报 TypeError: object MagicMock can't be used in 'await' expression。
- 必须用
AsyncMock:通过mock.AsyncMock()构造返回值 - 例如:
mock.patch('api.session.get', return_value=mock.AsyncMock(return_value=mock_response)) - 注意
httpx.AsyncClient.get同理,不能只 mockhttpx.get(那是同步接口) - pytest-mock 0.12+ 原生支持
mock.AsyncMock,旧版本需升级或手动导入
为什么 patch 后断言没生效?常见失效原因
最常踩的坑不是语法错,而是 patch 目标路径不对或时机不对 —— mock 在 import 之后才生效,而模块顶层代码可能已执行。
- 检查被 patch 的模块是否被提前 import:比如
conftest.py里 import 了待测模块,会导致 patch 失效 - 路径拼写必须精确:大小写、包名层级、别名(如
import requests as req就得 patch'api.req') - 用
mock.patch.object替代字符串路径更安全,比如mock.patch.object(api.requests, 'get') - 避免在类方法中用
self.mock = mocker.patch(...),应统一用 fixture 参数或模块级 patch
复杂点在于:mock 的 scope(function/module/session)和 patch 的嵌套层级容易互相干扰,一旦行为异常,优先检查 patch 的 target 字符串是否和运行时 import 路径完全一致。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











