Reputation: 18353
I'm trying to write a unit test for a method that calls subprocess.Popen
. All I want to test is that arg
argument sent to Popen
is as expected. I don't actually want Popen
to run. Is this possible without mocking the arg
list?
e.g.
def call_something(argument_list):
binary = '/opt/mybin/'
Popen([binary] + argument_list)
Then, to test.
@mock.patch('subprocess.Popen')
def test_call_something(self, mock_popen):
binary = '/opt/mybin/'
args = ['foo', 'bar']
mock_popen.return_value.returncode = 0
mock_popen.return_value.communicate.return_value = ('Running', '')
call_something(args)
self.assertEqual(
[binary] + args,
mock_popen.call_args_list
)
The issues I'm getting here is that, first the binary is called (which I don't want) and second, call_args_list
is empty.
Upvotes: 2
Views: 4100
Reputation: 141
When using mock.patch
you must point to the object where it is imported
See the documentation and this article that explains it well.
For example, in your case:
code.py
from subprocess import Popen
def call_something(argument_list):
binary = '/opt/mybin/'
Popen([binary] + argument_list)
test.py (Assuming both file are in the same folder, you need to patch code.Popen
and not subprocess.Popen
in the test)
from code import call_something
@mock.patch('code.Popen')
def test_call_something(self, mock_popen):
binary = '/opt/mybin/'
args = ['foo', 'bar']
mock_popen.return_value.returncode = 0
mock_popen.return_value.communicate.return_value = ('Running', '')
call_something(args)
self.assertEqual(
[binary] + args,
mock_popen.call_args_list
)
Upvotes: 6