Python如何mock相对路径导入的对象且无需使用绝对路径
Python相对路径导入对象的Mock方案
unittest.mock.patch 不关心被测试代码用的是相对导入还是绝对导入,核心规则是你要Mock哪个模块里用到的对象,就定位到该模块的命名空间下的对应对象,不需要修改原业务代码的相对导入写法。
具体实现方案(结合你给出的场景)
假设你的项目目录结构如下:
your_project/ ├── test_libs/ │ └── some_path/ │ ├── some_module.py # 内部定义了something对象 │ └── target_module.py # 被测试文件,用相对导入引入something └── tests/ └── test_target.py # 测试代码文件
你的被测试文件target_module.py内的代码无需修改,保留相对导入即可:
from ..some_module import something # 保留原有相对导入写法
测试代码中不要去Patch对象定义的原始路径,改为Patch被测试模块命名空间下的对象即可:
from unittest.mock import patch from test_libs.some_path.target_module import 你要测试的业务方法 # 注意这里的路径是「被测试模块的全路径 + 导入的对象名」,不是对象定义的原始路径 @patch('test_libs.some_path.target_module.something.method') def test_something(mock_method): # 配置Mock返回值 mock_method.return_value = "预期的Mock返回结果" # 执行测试逻辑 你要测试的业务方法() # 校验调用符合预期 mock_method.assert_called_once()
常见注意事项
- 如果要Mock整个
something对象而非它的某个方法,只需要将Patch路径改为test_libs.some_path.target_module.something即可 - 原业务代码的相对导入逻辑完全不需要调整,也不需要强制改为绝对导入
- 不要直接Patch对象定义的原始路径(也就是你之前写的
test_libs.some_path.some_module.something.method):被测试模块已经将something导入到了自己的命名空间下,修改原始路径的Mock不会作用到被测试模块已经导入的对象上
内容的提问来源于stack exchange,提问作者dondublon
相关产品推荐
相关产品推荐

