Это немного продолжение этого вопроса.
Я пытаюсь написать модульный тест, чтобы смоделировать вызов на Popen.communicate()
, где происходит TimeoutExpired
.Пока у меня есть:
benchmark.py
from subprocess import Popen, PIPE
from signal import SIGINT
from subprocess import TimeoutExpired
def some_func():
with Popen(["sleep","10","ls"], stdout=PIPE, stderr=PIPE) as proc:
try:
stdout, stderr = proc.communicate(timeout=5)
# some more logic here ...
except TimeoutExpired:
print('timeout')
proc.send_signal(SIGINT)
proc.wait()
proc.kill()
stdout, stderr = proc.communicate()
# some other logic here ...
test.py
import mock, unittest, benchmark
from subprocess import TimeoutExpired
class TestBenchmark(unittest.TestCase):
@mock.patch('benchmark.Popen')
def test_some_func(self, mock_popen):
process = mock_popen.return_value.__enter__.return_value
process.returncode = 0
process.communicate.return_value = (b'some output', b'some error')
process.communicate.side_effect = TimeoutExpired
# process.timeout = 2
# process.communicate.timeout = 2
# process.communicate.__init__.timeout = 2
# process.__init__(timeout=2)
foo = benchmark.some_func()
Asнаписано, я получаю
TypeError: __init__() missing 2 required positional arguments: 'cmd' and 'timeout'
Я пробовал несколько способов насмешки над аргументом тайм-аута, но я не понимаю правильный способ сделать это.
Кроме того, хотя яМеня не беспокоит возвращаемое значение первого вызова communicate()
, я пытаюсь смоделировать значения второго вызова (except TimeoutExpired
).Из документов я знаю, что:
Если side_effect является итеративным, то каждый вызов mock будет возвращать следующее значение из итерируемого.
Как я могу использовать side_effect
, чтобы вызвать исключение и убедиться, что я правильно высмеиваю второй вызов communicate()
?