Jat*_*mir 5 python unit-testing mocking pytest python-3.x
我正在自动化一些存储库操作,并使用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()
Run Code Online (Sandbox Code Playgroud)
但是,我注意到该类Git有些特殊并且没有实现pull. 相反,它将所有流量“委托”给__getattr__使用另一种方法来完成这项工作。
def __getattr__(self, name):
...
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
我的问题是如何进行测试?我将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()
Run Code Online (Sandbox Code Playgroud)
它们都有效,但我觉得有更好的方法,也许我的测试方法是错误的。
感谢jonrsharpe指导我使用create参数,我成功地通过以下代码实现了我想要的目标:
def test_pull(mocker: MockFixture) -> None:\n m = mocker.patch.object(Git, \'pull\', create=True)\n pull()\n m.assert_called_once_with()\nRun Code Online (Sandbox Code Playgroud)\n\n摘自文档解释了什么create=True:
\n\n默认情况下 patch() 将无法替换不存在的属性。如果你传入create=True,并且该属性不存在\xe2\x80\x99,patch会在调用patch函数时为你创建该属性,并在之后再次删除它。
\n
| 归档时间: |
|
| 查看次数: |
3560 次 |
| 最近记录: |