从 __getattr__ 方法中检索到的模拟函数
Mocking functions retrieved from __getattr__ method
我正在自动执行一些存储库操作,我正在使用 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
class 有点特殊,没有实现 pull
。相反,它 "delegates" 所有流量到 __getattr__
,它使用另一种方法来完成这项工作。
def __getattr__(self, name):
...
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
我的问题是如何进行测试?我正在使用 pytest with 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()
它们都有效,但我觉得有更好的方法,也许我的测试方法是错误的。
感谢 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
的作用:
By default patch() will fail to replace attributes that don’t exist. If you pass in create=True, and the attribute doesn’t exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards.
我正在自动执行一些存储库操作,我正在使用 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
class 有点特殊,没有实现 pull
。相反,它 "delegates" 所有流量到 __getattr__
,它使用另一种方法来完成这项工作。
def __getattr__(self, name):
...
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
我的问题是如何进行测试?我正在使用 pytest with 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()
它们都有效,但我觉得有更好的方法,也许我的测试方法是错误的。
感谢 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
的作用:
By default patch() will fail to replace attributes that don’t exist. If you pass in create=True, and the attribute doesn’t exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards.