#python #mocking #subprocess #pytest #try-except
#python #издевательство #подпроцесс #pytest #попробуйте-кроме
Вопрос:
Я использую 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()
По какой-то причине это не работает, и я не могу понять, что не так.
Ответ №1:
Если вы хотите протестировать функциональность class ( Check
), вы не можете издеваться над этим классом. Вместо этого вам нужно издеваться над вызовами, которые вы хотите изменить — в данном случае, вероятно 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», потому что вы импортируете
check_output
с помощьюfrom subprocess import check_output
, поэтому вы используете ссылку в своем классе - вы должны создать допустимый
TimeoutExpired
объект — для него требуется 2 аргумента, поэтому вы должны их предоставить - как
get_status
уже было вызвано__init__
, вы должны протестировать конструкцию класса — вы не можете получить правильно сконструированный экземпляр из-за возникшего исключения