如何通过pytest-mock对已导入函数实施桩化(patching)以模拟行为?
- 内容介绍
- 相关推荐
本文共计661个文字,预计阅读时间需要3分钟。
相关主题
在 pytest 中使用 mocker.patch 时,若函数已被 `from ... import ...` 导入,需 patch 当前模块中该函数的引用名(如 `f"{__name__}.get_a"`),而非其原始定义位置(如 `"mypackage.mymodule.get_a"`),否则打桩失效。
这是 Python 导入机制与 unittest.mock.patch 工作原理共同决定的关键行为:mock 总是作用于“被调用处所引用的对象”,而非“对象最初定义的位置”。
? 问题根源解析
当你执行:
from mypackage.mymodule import A, get_a
Python 将 mypackage.mymodule.get_a 的引用复制到当前模块的命名空间中,变量 get_a 成为一个独立的本地标识符。后续代码中调用 get_a() 实际访问的是 当前模块中的 get_a 名称绑定,而非动态查找 mypackage.mymodule.get_a。
因此,若你 patch "mypackage.mymodule.get_a",仅修改了源模块中该属性(对当前模块无影响);而真正被调用的 get_a 仍指向原函数 —— 所以 mock 失效。
本文共计661个文字,预计阅读时间需要3分钟。
相关主题
在 pytest 中使用 mocker.patch 时,若函数已被 `from ... import ...` 导入,需 patch 当前模块中该函数的引用名(如 `f"{__name__}.get_a"`),而非其原始定义位置(如 `"mypackage.mymodule.get_a"`),否则打桩失效。
这是 Python 导入机制与 unittest.mock.patch 工作原理共同决定的关键行为:mock 总是作用于“被调用处所引用的对象”,而非“对象最初定义的位置”。
? 问题根源解析
当你执行:
from mypackage.mymodule import A, get_a
Python 将 mypackage.mymodule.get_a 的引用复制到当前模块的命名空间中,变量 get_a 成为一个独立的本地标识符。后续代码中调用 get_a() 实际访问的是 当前模块中的 get_a 名称绑定,而非动态查找 mypackage.mymodule.get_a。
因此,若你 patch "mypackage.mymodule.get_a",仅修改了源模块中该属性(对当前模块无影响);而真正被调用的 get_a 仍指向原函数 —— 所以 mock 失效。

