如何在测试a.do_something时Mock b中导入的my_other_func?
正确Mock跨模块底层依赖的方法
问题场景
现有代码结构如下:
a.py
from b import my_func def do_something(): my_func()
b.py
from c import my_other_func # 测试时需要Mock这个函数(屏蔽其内部数据库调用) def my_func(): my_other_func()
需要为a.do_something()编写单元测试,要求保留b.my_func的原有逻辑,仅Mock底层的my_other_func,但尝试mock.patch("a.b.my_other_func")、mock.patch("b.my_other_func")均未正确生效。
解决方案
核心要理解Python的模块引用机制:当b.py执行from c import my_other_func时,会将c.my_other_func的引用复制到b模块的命名空间中,b.my_func实际调用的是b模块内的这个引用,而非c模块的原函数。
正确的Patch路径
必须针对b模块内的my_other_func引用进行Patch,即使用路径"b.my_other_func",但要注意导入顺序:必须先完成Patch,再导入被测试的a或b模块,否则原引用会被提前加载,Patch无法覆盖。
测试代码示例
用装饰器实现
from unittest import mock, unittest class TestDoSomething(unittest.TestCase): @mock.patch("b.my_other_func") def test_do_something(self, mock_my_other_func): # 延迟导入被测试模块,确保Patch已生效 from a import do_something do_something() # 验证Mock函数被调用 mock_my_other_func.assert_called_once() if __name__ == "__main__": unittest.main()
用上下文管理器实现
from unittest import mock def test_do_something(): with mock.patch("b.my_other_func") as mock_my_other_func: from a import do_something do_something() mock_my_other_func.assert_called_once()
常见失败原因
- 使用
"a.b.my_other_func"路径:错误,a模块仅导入了b.my_func,不存在a.b子模块,路径无效。 - Patch前提前导入
a/b:如果测试文件在Patch执行前就导入了a或b,b模块内的my_other_func引用已被固定,后续Patch无法覆盖这个引用。
内容的提问来源于stack exchange,提问作者michjo
相关产品推荐
相关产品推荐

