Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to mock subprocess.call in a unittest

I'm on python 3.3 and I have to test a method which use call from subprocess.py.

I tried:

subprocess.call = MagicMock()

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

but in debug mode I found that python call effectively subprocess.call

like image 786
beyrem Avatar asked Oct 04 '13 11:10

beyrem


1 Answers

Works fine for me (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')]

I believe this question is about the usage of this particular mock package

General statements, unrelated to your direct question

Wrote this up before I understood that the question is specifically about the use of the python mock package.

One general way to mock functions is to explicitly redefine the function or method:

$ 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'

The big advantage of this straightforward approach is that this is free of any package dependencies. The disadvantage is that if there are specific needs, all the decision making logic has to be coded manually.

As an example of mocking packages, FlexMock is available for both Python 2.7 and Python 3.* and its usage of overriding subprocess.call is discussed in this question

like image 62
cfi Avatar answered Sep 17 '22 14:09

cfi