如何在 pytest 中模拟 subprocess.run?
How to mock subprocess.run in pytest?
我有 class InternalProc,定义如下:
class InternalProc:
@staticmethod
def get_data():
try:
result = subprocess.run(['bridge-client', '--business-credentials'],
stdout=subprocess.PIPE)
data = json.loads(result.stdout.decode('utf-8'))
return data
except Exception:
logger.error("Unable to fetch the data")
raise
我想对 get_data()
进行单元测试,我应该如何模拟 subprocess.run
?我还想断言是否引发了异常。
似乎您需要两个测试来测试此方法,一个是 returns 数据,另一个是引发 Exception
.
对于我们 return 数据的数据,我们只需要模拟 subprocess.run
。然后我们可以创建另一个 Mock
对象来模拟 stdout.decode
到 return 数据 json.loads
可以解析。这意味着为 stdout
的行为创建一个 Mock
对象,然后配置我们模拟的 subprocess.run
来使用这个对象。
对于另一个测试,我们只需要使用 Mock
对象的 side_effect
kwarg 在调用时引发异常。
给定以下文件夹结构:
Whosebug/
├── mypackage
│ ├── __init__.py
│ └── proc.py
└── tests
├── __init__.py
└── test_proc.py
我们编写的测试如下所示。
from unittest.mock import MagicMock, patch
import pytest
from mypackage.proc import InternalProc
@patch("mypackage.proc.subprocess.run")
def test_get_data_valid(mock_run):
mock_stdout = MagicMock()
mock_stdout.configure_mock(
**{
"stdout.decode.return_value": '{"A": 3}'
}
)
mock_run.return_value = mock_stdout
result = InternalProc.get_data()
assert result == {"A": 3}
@patch("mypackage.proc.subprocess.run", side_effect=Exception("foobar"))
def test_get_data_invalid(mock_run):
with pytest.raises(Exception) as exc:
InternalProc.get_data()
assert "foobar" in str(exc.value)
输出:
======================================= test session starts ========================================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: ***/Whosebug
collected 2 items
tests/test_proc.py .. [100%]
======================================== 2 passed in 0.07s =========================================
我对你的建议是,因为我在过去几天看到你 post 多个 pytest
/mock
问题,所以我建议你花一些时间阅读这两个问题的文档。制作一些玩具示例并试用这两个包。这是您学习如何模拟以及在何处模拟的唯一方法。
我有 class InternalProc,定义如下:
class InternalProc:
@staticmethod
def get_data():
try:
result = subprocess.run(['bridge-client', '--business-credentials'],
stdout=subprocess.PIPE)
data = json.loads(result.stdout.decode('utf-8'))
return data
except Exception:
logger.error("Unable to fetch the data")
raise
我想对 get_data()
进行单元测试,我应该如何模拟 subprocess.run
?我还想断言是否引发了异常。
似乎您需要两个测试来测试此方法,一个是 returns 数据,另一个是引发 Exception
.
对于我们 return 数据的数据,我们只需要模拟 subprocess.run
。然后我们可以创建另一个 Mock
对象来模拟 stdout.decode
到 return 数据 json.loads
可以解析。这意味着为 stdout
的行为创建一个 Mock
对象,然后配置我们模拟的 subprocess.run
来使用这个对象。
对于另一个测试,我们只需要使用 Mock
对象的 side_effect
kwarg 在调用时引发异常。
给定以下文件夹结构:
Whosebug/
├── mypackage
│ ├── __init__.py
│ └── proc.py
└── tests
├── __init__.py
└── test_proc.py
我们编写的测试如下所示。
from unittest.mock import MagicMock, patch
import pytest
from mypackage.proc import InternalProc
@patch("mypackage.proc.subprocess.run")
def test_get_data_valid(mock_run):
mock_stdout = MagicMock()
mock_stdout.configure_mock(
**{
"stdout.decode.return_value": '{"A": 3}'
}
)
mock_run.return_value = mock_stdout
result = InternalProc.get_data()
assert result == {"A": 3}
@patch("mypackage.proc.subprocess.run", side_effect=Exception("foobar"))
def test_get_data_invalid(mock_run):
with pytest.raises(Exception) as exc:
InternalProc.get_data()
assert "foobar" in str(exc.value)
输出:
======================================= test session starts ========================================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: ***/Whosebug
collected 2 items
tests/test_proc.py .. [100%]
======================================== 2 passed in 0.07s =========================================
我对你的建议是,因为我在过去几天看到你 post 多个 pytest
/mock
问题,所以我建议你花一些时间阅读这两个问题的文档。制作一些玩具示例并试用这两个包。这是您学习如何模拟以及在何处模拟的唯一方法。