pytest-mock 的 mocker 夹具是什么
pytest-mock 提供 mocker 夹具,封装 unittest.mock 的 patch 与 spy,随用例自动清理:相比手写上下文管理器样板更少,还能与 fixture 系统组合。它适合替换依赖模块的行为、记录调用次数与参数,用例结束后统一还原,不留全局残留。
基本信息
| 核心对象 | mocker 夹具,封装 patch 与 spy |
|---|---|
| 清理 | 用例结束自动还原,无需 with 与 addCleanup |
| 常用方法 | patch、spy、stub、patch.object、patch.dict |
| 断言接口 | assert_called_once、assert_called_with 等来自 Mock |
| 适用边界 | 替换依赖与外部协作对象,不深入被测内部实现 |
补丁与间谍
补丁与间谍
def test_submit(mocker):
# 替换依赖并断言调用
send = mocker.patch("app.mailer.send", return_value=True)
order.submit()
send.assert_called_once()
def test_spy(mocker):
# 间谍:保留原实现,只记录调用
spy = mocker.spy(cart, "total")
cart.checkout()
spy.assert_called()典型使用场景
- 隔离外部依赖:邮件、支付、短信调用替换为桩。
- 调用契约:断言调用次数与关键参数,验证协作协议。
- 失败演练:让依赖抛异常,验证重试与降级路径。
- 部分替换:spy 保留原实现只做观察记录。
- 字典与配置:patch.dict 临时覆盖配置项。
- 样板收敛:把散落的 unittest.mock 样板收敛到 mocker。
常用方法
| 方法 | 行为 | 场景 |
|---|---|---|
| patch | 替换目标并返回 Mock | 依赖隔离 |
| spy | 保留实现、记录调用 | 观察协作 |
| stub | 替换并返回默认值 | 占位 |
| patch.dict | 临时改字典内容 | 配置覆盖 |
替换范围尽量止步于依赖模块,不要深入到被测对象的内部实现,避免断言绑定实现细节。
patch 目标遵循「patch 使用方」原则:from x import y 之后,要 patch 使用方模块里的名字。
断言要点
- 调用次数:assert_called_once 与 call_count 结合看。
- 调用参数:assert_called_with 校验关键参数,避免只数次数。
- 调用顺序:多个依赖间用 mock_calls 核对相对顺序。
- 未调用断言:assert_not_called 验证短路与缓存路径。
打桩建议带 spec:以真实对象为规格创建 Mock,拼错的属性或参数会直接报错,而不是静默通过。
mock 嵌套保持在一层:多层 mock 让断言脆弱,必要时改造为接口级桩。