When attempting to mock Popen I can only get it to succeed if the importing of subprocess matches in both unit test code and main module code.
Given following module listdir.py:
from subprocess import Popen, PIPE
def listdir(dir):
cmd = ['ls', dir]
pc = Popen(cmd, stdout=PIPE, stderr=PIPE)
out, err = pc.communicate()
if pc.returncode != 0:
raise Exception
return out
and following unit test code test_listdir.py
import subprocess
import listdir
import mock
@mock.patch.object(subprocess, 'Popen', autospec=True)
def test_listdir(mock_popen):
mock_popen.return_value.returncode = 0
mock_popen.return_value.communicate.return_value = ("output", "Error")
listdir.listdir("/fake_dir")
For some reason Popen is not being mocked, due to the import style being different between the two python modules, and running the test always raises an exception.
If I change listdir.py to import all of subproces e.g.
import subprocess
def listdir(dir):
cmd = ['ls', dir]
pc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = pc.communicate()
if pc.returncode != 0:
raise ListingErrorException
return out
Then "output" is returned in the test.
Anyone care to shed some light on why, my preference would be to have from subprocess import Popen, Pipe in both modules, but I just can't get that to mock.
You need to patch the copy of Popen in listdir, not the one you just imported. So, instead of @mock.patch.object(subprocess, 'Popen', autospec=True)
, try @mock.patch.object(listdir, 'Popen', autospec=True)
See this doc for more info: http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With