我正在自动执行一些存储库操作,并且正在为此工作使用GitPython。让我们简化事情,并假设我想断言我的函数是否在存储库上称为pull
方法。下面的代码:
from pytest_mock import MockFixture
from git import Git, Repo
repo = Repo('/Users/Jatimir/path/to/repo')
def pull() -> None:
repo.git.pull()
但是,我注意到Git
类有点特殊,并且没有实现pull
。而是将所有流量“委派”到__getattr__
,后者使用另一种方法完成任务。
def __getattr__(self, name):
...
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
我的问题是如何进行测试?我正在将pytest与pytest-mock配合使用,它提供了mocker
固定装置,这是我的尝试:
def test_pull1(mocker: MockFixture) -> None:
pull_mock = mocker.MagicMock(name='pull')
getattr_mock = mocker.MagicMock(name='__getattr__', return_value=pull_mock)
mocker.patch.object(Git, '__getattr__', getattr_mock)
pull()
pull_mock.assert_called_once_with()
def test_pull2(mocker: MockFixture) -> None:
pull_mock = mocker.Mock(name='pull')
def __getattr__(self, name):
if name == 'pull':
return pull_mock
mocker.patch.object(Git, '__getattr__', __getattr__)
pull()
pull_mock.assert_called_once_with()
它们都可以工作,但是我觉得有更好的方法,也许我的测试方法是错误的。
答案 0 :(得分:4)
感谢jonrsharpe指导我使用create
参数,我设法通过以下代码实现了我想要的:
def test_pull(mocker: MockFixture) -> None:
m = mocker.patch.object(Git, 'pull', create=True)
pull()
m.assert_called_once_with()
从documentation摘录来解释create=True
的作用:
默认情况下,patch()将无法替换不存在的属性。如果您传入create = True且该属性不存在,则修补程序将在调用已修补的函数时为您创建该属性,然后再将其删除。