Как насмехать subprocess.call в unittest

Я на python 3.3, и мне нужно протестировать метод, который использует call из subprocess.py.

Я пробовал:

subprocess.call = MagicMock()

with patch('subprocess.call') as TU_call:

но в режиме отладки я обнаружил, что вызов python эффективно subprocess.call

Ответ 1

Прекрасно работает для меня (Ubuntu 13.04, Python 3.3.1):

$ python3.3
Python 3.3.1 (default, Sep 25 2013, 19:29:01) 
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mock
>>> import subprocess
>>> result = subprocess.call('date')
Fri Jan  3 19:45:32 CET 2014
>>> subprocess.call = mock.create_autospec(subprocess.call, return_value='mocked!')
>>> result = subprocess.call('date')
>>> print(result)
mocked!
>>> subprocess.call.mock_calls
[call('date')]

Я считаю, что этот вопрос касается использования этого конкретного mock package

Общие утверждения, не связанные с вашим прямым вопросом

Написал это до того, как понял, что вопрос касается использования пакета python mock.

Один общий способ издеваться над функциями - явно переопределить функцию или метод:

$ python3.3
Python 3.3.1 (default, Sep 25 2013, 19:29:01) 
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.call('date')
Fri Jan  3 19:23:25 CET 2014
0
>>> def mocked_call(*a, **kw):
...   return 'mocked'
... 
>>> subprocess.call = mocked_call
>>> subprocess.call('date')
'mocked'

Большое преимущество этого простого подхода заключается в том, что в нем нет любых зависимостей пакетов. Недостатком является то, что при наличии конкретных потребностей вся логика принятия решений должна быть закодирована вручную.

В качестве примера издевательских пакетов FlexMock is доступный для Python 2.7 и Python 3. *, а его использование переопределения subprocess.call обсуждается в этом вопросе

Ответ 2

Эта работа для subprocess.check_output в python3

    @mock.patch('subprocess.check_output', mock.mock_open())
    @mock.patch('subprocess.Popen.communicate')
    def tst_prepare_data_for_matrices(self, makedirs_mock, check_output_mock):
        config_file = open(os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)+'/etc/test/config.json')).read()
        check_output_mock.return_value = ("output", "Error")