jeudi 25 juin 2015

mocking subprocess.Popen dependant on import style

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.

Aucun commentaire:

Enregistrer un commentaire