2015-06-25 4 views
3

При попытке издеваться над Popen я могу добиться успеха только в том случае, если импорт подпроцесса совпадает как с модульным тестовым кодом, так и с кодом основного модуля.mocking subprocess.Popen в зависимости от стиля импорта

Учитывая следующий модуль 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 

и после модульного тестирования кода 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") 

По какой-то причине Popen не дразнят из-за стиль импорта быть различались два модуля python и запуск теста всегда вызывает исключение.

Если я изменяю listdir.py для импорта всех подпрограмм, например.

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 

После этого в тесте возвращается «выход».

Любой, кто хочет пролить свет на то, почему, мое предпочтение было бы иметь из подпроцесса импорт Popen, Pipe в обоих модулях, но я просто не могу понять это, чтобы насмехаться.

ответ

6

Вам необходимо исправить копию Popen в listdir, а не тот, который вы только что импортировали. Таким образом, вместо @mock.patch.object(subprocess, 'Popen', autospec=True), попробуйте @mock.patch.object(listdir, 'Popen', autospec=True)

Смотрите этот документ для получения дополнительной информации: http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch

+0

Perfect, спасибо –