如何模拟:pytest.raises 没有加注 <class 'subprocess.TimeoutExpired'>
How to Mock: pytest.raises DID NOT RAISE <class 'subprocess.TimeoutExpired'>
我正在使用 subprocess
完成一项任务,并且我有一个 try/except
块用于捕获 TimeoutExpired
。我尝试使用 side_effect
模拟我的对象,这样我就可以使用 pytest.raises
捕获假异常。无论我做什么,我都会得到 DID NOT RAISE <class 'subprocess.TimeoutExpired'>
。
我已经尝试了很多东西,尽管我对模拟没有那么丰富的经验,但我相信这样的事情原则上应该可行:
# my_check.py
from subprocess import TimeoutExpired, PIPE, check_output
class Check:
def __init__(self, name):
self.name = name
self.status = self.get_status()
def get_status(self):
try:
out = check_output(["ls"], universal_newlines=True, stderr=PIPE, timeout=2)
except TimeoutExpired as e:
print(f"Command timed out: {e}")
raise
if self.name in out:
return True
return False
# test_my_check.py
import pytest
from unittest import mock
from subprocess import TimeoutExpired
@mock.patch("src.my_check.Check", autospec=True)
def test_is_installed_exception(check_fake):
check_fake.get_status.side_effect = TimeoutExpired
obj_fake = check_fake("random_file.txt")
with pytest.raises(TimeoutExpired):
obj_fake.get_status()
由于某种原因它不起作用,我无法理解哪里出了问题。
如果您想测试 class (Check
) 的功能,您不能模拟 class。您必须模拟您想要更改的调用 - 在这种情况下可能 check_output
,您想要引发异常:
@mock.patch("src.my_check.check_output")
def test_is_installed_exception(mocked_check_output):
mocked_check_output.side_effect = TimeoutExpired("check_output", 1)
with pytest.raises(TimeoutExpired):
Check("random_file.txt")
一些注意事项:
- 您必须修补“src.my_check.check_output”,因为您使用
from subprocess import check_output
导入 check_output
,所以您使用 class 中的引用
- 您必须构造一个有效的
TimeoutExpired
对象 - 它需要 2 个参数,因此您必须提供它们
- 由于
get_status
已在 __init__
中调用,您必须测试 class 构造 - 由于引发的异常 [=26],您无法获得正确构造的实例=]
我正在使用 subprocess
完成一项任务,并且我有一个 try/except
块用于捕获 TimeoutExpired
。我尝试使用 side_effect
模拟我的对象,这样我就可以使用 pytest.raises
捕获假异常。无论我做什么,我都会得到 DID NOT RAISE <class 'subprocess.TimeoutExpired'>
。
我已经尝试了很多东西,尽管我对模拟没有那么丰富的经验,但我相信这样的事情原则上应该可行:
# my_check.py
from subprocess import TimeoutExpired, PIPE, check_output
class Check:
def __init__(self, name):
self.name = name
self.status = self.get_status()
def get_status(self):
try:
out = check_output(["ls"], universal_newlines=True, stderr=PIPE, timeout=2)
except TimeoutExpired as e:
print(f"Command timed out: {e}")
raise
if self.name in out:
return True
return False
# test_my_check.py
import pytest
from unittest import mock
from subprocess import TimeoutExpired
@mock.patch("src.my_check.Check", autospec=True)
def test_is_installed_exception(check_fake):
check_fake.get_status.side_effect = TimeoutExpired
obj_fake = check_fake("random_file.txt")
with pytest.raises(TimeoutExpired):
obj_fake.get_status()
由于某种原因它不起作用,我无法理解哪里出了问题。
如果您想测试 class (Check
) 的功能,您不能模拟 class。您必须模拟您想要更改的调用 - 在这种情况下可能 check_output
,您想要引发异常:
@mock.patch("src.my_check.check_output")
def test_is_installed_exception(mocked_check_output):
mocked_check_output.side_effect = TimeoutExpired("check_output", 1)
with pytest.raises(TimeoutExpired):
Check("random_file.txt")
一些注意事项:
- 您必须修补“src.my_check.check_output”,因为您使用
from subprocess import check_output
导入check_output
,所以您使用 class 中的引用
- 您必须构造一个有效的
TimeoutExpired
对象 - 它需要 2 个参数,因此您必须提供它们 - 由于
get_status
已在__init__
中调用,您必须测试 class 构造 - 由于引发的异常 [=26],您无法获得正确构造的实例=]