我正在尝试使用 pytest 编写单元测试来模拟
subprocess.run
调用这里的其他一些示例,但遇到了困难。我有以下课程:
class Bmx:
def version(self) -> Tuple[int, int, int]:
cmd = [self.exec_path, '-v']
err, out = self._run(cmd)
version = re.search(r'v\d+\.\d+\.\d+', out, re.IGNORECASE)[0][1:].split('.')
return int(version[0]), int(version[1]), int(version[2])
@staticmethod
def _run(cmd: List[str], shell: bool = False) -> Tuple[str, str]:
proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=shell, universal_newlines=True)
if proc.returncode > 0:
raise BmxError(proc.stderr)
return proc.stderr, proc.stdout
我试着为
version
方法写了一个单元测试如下:
from unittest.mock import MagicMock, patch
import pytest
from pybmx.bmx import Bmx
@patch('pybmx.bmx.subprocess.run')
def test_version(mock_run):
mock_proc = MagicMock()
mock_proc.configure_mock(**{
'returncode.return_value': 0,
'stdout.return_value': 'raw2bmx, bmx v1.1.6, Mar 3 2023 10:02:28 (scm v1.1-6-g43fac95-dirty)'
})
mock_run.return_value = mock_proc
assert Bmx('raw2bmx').version() == (1, 1, 6)
但是测试失败,出现以下情况:
@staticmethod
def _run(cmd: List[str], shell: bool = False) -> Tuple[str, str]:
proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=shell, universal_newlines=True)
> if proc.returncode > 0:
E TypeError: '>' not supported between instances of 'MagicMock' and 'int'
我认为通过使用 MagicMock
returncode.return_value
方法配置 configure
我会模拟返回代码,但我似乎没有正确理解这一点。我也想知道是否有办法用pytest
而不是unittest
来实现这一点。任何意见,将不胜感激!谢谢。
问题好像是
mock_proc.configure_mock(**{"f.return_value": ...})
用于模拟方法,但 proc.returncode
是一个属性。
不过,模拟属性甚至更容易(请参阅文档):
>>> m = MagicMock(attribute=3, other='fish')
>>> m.attribute
3
>>> m.other
'fish'