Mocking a subprocess call in Python

It seems unusual to me that you use the patch decorator over the run_script function, since you don’t pass a mock argument there.

How about this:

from unittest import mock
import subprocess

def run_script(file_path):
    process = subprocess.Popen(["myscript", -M, file_path], stdout=subprocess.PIPE)
    output, err = process.communicate()
    return process.returncode


@mock.patch("subprocess.Popen")
def test_run_script(self, mock_subproc_popen):
    process_mock = mock.Mock()
    attrs = {"communicate.return_value": ("output", "error")}
    process_mock.configure_mock(**attrs)
    mock_subproc_popen.return_value = process_mock
    am.account_manager("path")  # this calls run_script somewhere, is that right?
    self.assertTrue(mock_subproc_popen.called)

Right now, your mocked subprocess.Popen seems to return a tuple, causeing process.communicate() to raise TypeError: 'tuple' object is not callable.. Therefore it’s most important to get the return_value on mock_subproc_popen just right.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)