Reputation: 5442
I'm trying to mock multiple functions inside a module, from within a TestCase:
from mock import patch, DEFAULT, Mock
function_a = Mock()
function_a.return_value = ['a', 'list']
with patch.multiple('target.module',
function_a=function_a,
function_b=DEFAULT) as (f_a, f_b):
To my surprise, this is not working, giving me the following Traceback:
ValueError: need more than 1 value to unpack
using: http://www.voidspace.org.uk/python/mock/
Upvotes: 4
Views: 8131
Reputation: 5516
You can use Parenthesized Context Managers to patch multiple thing with Python 3.10 like so:
from unittest.mock import patch, DEFAULT, Mock
def setup():
with (
patch("target.module.function_a", Mock(), return_value = ['a', 'list']) as f_a,
patch("target.module.function_b", DEFAULT) as f_b,
):
# proceed to test
Upvotes: 1
Reputation: 1610
For patch.multiple
, assigning the patched function name (function_a
) to any value other than DEFAULT
, or unittest.mock.DEFAULT
, will result in the returned dictionary not containing the mocked function.
In other words,
with patch.multiple('target.module', func_a=SOME_VALUE, func_b=DEFAULT) as mocks:
mocks['func_a'] # KeyError: 'func_a'
Also, assigning with patch.multiple(...) as (f_a, f_b)
is going to give you two strings, which in your case will be 'function_a'
and 'function_b'
. This is equivalent to the operation
x = dict(function_a = MagicMock_a, function_b = MagicMock_b)
(f_a, f_b) = x
f_a # 'function_a'
If you wish to access the MagicMock
object, assign it to the dictionary value instead, something like mocks['func_a'] = f_a
.
Upvotes: 5
Reputation: 600041
So, from that documentation page you link to:
If patch.multiple is used as a context manager, the value returned by the context manger is a dictionary where created mocks are keyed by name
But you've got with patch.multiple(...) as (f_a, f_b)
- two values. Looks like it should be with patch.multiple(...) as fdict
, and fdict
will be a dictionary with keys function_a
and function_b
.
Upvotes: 3