I am writing a program which creates a subprocess.Popen
pipeline. I'm trying to mock subprocess.Popen
such that each call returns a distinct MagicMock
so I can ensure methods are called on specific (or all) processes in the pipeline.
I also want this mock to be autospec'd based on subprocess.Popen
but keep getting an error that I can't autospec based on a mock.
Currently my code is as follows:
@pytest.fixture
def Popen(mocker: 'pytest_mock.MockFixture'):
def popen_factory(*args, **kwargs):
popen = mocker.MagicMock() # mocker.create_autospec(subprocess.Popen)
popen.stdin = open(os.devnull, "wb")
popen.stdout = open(os.devnull, "rb")
popen.wait.return_value = 0
return popen
Popen = mocker.patch.object(subprocess, 'Popen', autospec=True)
Popen.side_effect = popen_factory
yield Popen
Since mocker.patch.object(subprocess, 'Popen', autospec=True)
overwrites subprocess.Popen
, I have to assign the existing value to a local variable, and use that instead.
@pytest.fixture
def Popen(mocker: 'pytest_mock.MockFixture'):
real_Popen = subprocess.Popen
def popen_factory(*args, **kwargs):
popen = mocker.create_autospec(real_Popen)
popen.stdin = open(os.devnull, "wb")
popen.stdout = open(os.devnull, "rb")
popen.wait.return_value = 0
return popen
Popen = mocker.patch.object(subprocess, 'Popen', autospec=True)
Popen.side_effect = popen_factory
yield Popen