如何用pytest Mock subprocess.run返回值?解决测试TypeError问题
问题分析与解决
错误原因
你在Mock subprocess.run返回的进程对象时,错误地使用了returncode.return_value来配置属性。returncode是subprocess.CompletedProcess的直接属性(不是可调用方法),不需要加.return_value。原写法会让mock_proc.returncode变成一个MagicMock对象,而非整数0,导致和整数比较时抛出类型错误。
修正后的unittest.mock写法
直接在configure_mock里设置returncode=0,同时stdout也是属性,同样不需要.return_value:
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': 0, 'stdout': 'raw2bmx, bmx v1.1.6, Mar 3 2023 10:02:28 (scm v1.1-6-g43fac95-dirty)', 'stderr': '' # 可选,_run返回stderr,这里设为空字符串即可 }) mock_run.return_value = mock_proc assert Bmx('raw2bmx').version() == (1, 1, 6)
不用unittest,直接用pytest的方案
可以使用pytest-mock插件(先安装:pip install pytest-mock),它封装了unittest.mock,提供更简洁的mocker fixture,无需导入patch:
import pytest from pybmx.bmx import Bmx def test_version(mocker): # Mock subprocess.run mock_run = mocker.patch('pybmx.bmx.subprocess.run') # 配置返回的进程对象 mock_run.return_value = mocker.Mock( returncode=0, stdout='raw2bmx, bmx v1.1.6, Mar 3 2023 10:02:28 (scm v1.1-6-g43fac95-dirty)', stderr='' ) assert Bmx('raw2bmx').version() == (1, 1, 6)
额外测试分支示例
如果需要测试错误分支(returncode>0的情况),可以设置returncode=1,并断言BmxError是否被正确抛出:
def test_version_error(mocker): mock_run = mocker.patch('pybmx.bmx.subprocess.run') mock_run.return_value = mocker.Mock( returncode=1, stderr='some error message' ) with pytest.raises(BmxError) as excinfo: Bmx('raw2bmx').version() assert excinfo.value.args[0] == 'some error message'
内容的提问来源于stack exchange,提问作者opnightfall1771
相关产品推荐
相关产品推荐

