如何在Python中模拟对象实例化及多Mock参数映射问题
问题解答
一、正确模拟Git Repo调用的方式
你报错NoSuchPathError的核心原因是patch的目标路径不对。unittest.mock.patch需要patch的是你的业务代码(someFile.py)中实际导入Repo的路径,而非Git库源码里的Repo路径。
举个例子:
如果你的someFile.py里是这么导入Repo的:
from git import Repo
那你测试时应该patchsomeFile.Repo,而不是git.repo.base.Repo。
具体测试代码示例:
from unittest.mock import patch, MagicMock from someFile import someFunction def test_some_function(): # Patch 业务代码中导入的Repo对象 with patch('someFile.Repo') as mock_repo_cls: # 模拟Repo实例 mock_repo = MagicMock() mock_repo_cls.return_value = mock_repo # 模拟commit方法返回的提交对象 mock_commit = MagicMock() mock_repo.commit.return_value = mock_commit # 模拟head属性 mock_head = MagicMock() mock_repo.head = mock_head # 调用待测试函数 someFunction() # 验证调用逻辑是否符合预期 mock_repo_cls.assert_called_once_with('somePath/path') # 替换成实际path参数 mock_repo.commit.assert_called_once_with('someHash') # 替换成实际someHash参数 mock_head.reset.assert_called_once_with(index=True, working_tree=True)
如果你的业务代码是用import git然后git.Repo调用的,那就要patchsomeFile.git.Repo,核心原则是patch的是待测试代码中实际引用该对象的路径。
二、多个Mock装饰器的参数映射规则
多个@mock.patch或@mock.patch.object装饰器的参数注入顺序是倒序的:
- 最靠近测试函数的装饰器,对应第一个参数;
- 最上方的装饰器,对应最后一个参数。
比如你给出的例子:
@mock.patch.object('target1') # 最上方的装饰器 @mock.patch.object('target2') @mock.patch.object('target3') # 最靠近测试函数的装饰器 def test_something(mocker3, mocker2, mocker1): pass
这里的映射关系是:
mocker3→@mock.patch.object('target3')生成的mock对象mocker2→@mock.patch.object('target2')生成的mock对象mocker1→@mock.patch.object('target1')生成的mock对象
简单记:装饰器从上到下排,参数从右到左接。
内容的提问来源于stack exchange,提问作者Shiva Shukla
相关产品推荐
相关产品推荐

