mock.reset_mock()
will not reset a side effect iterator. Is there a way to do this without creating the mock again?
>>> from mock import MagicMock
>>> mock = MagicMock(side_effect = [1,2])
>>> mock(), mock()
(1, 2)
>>> mock()
Traceback (most recent call last):
File "<pyshell#114>", line 1, in <module>
mock()
File "C:\Python27\Lib\site-packages\mock.py", line 955, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "C:\Python27\Lib\site-packages\mock.py", line 1013, in _mock_call
result = next(effect)
StopIteration
>>> mock.reset_mock()
>>> mock()
Traceback (most recent call last):
...
StopIteration
>>> mock = MagicMock(side_effect = [1,2])
>>> mock(), mock()
(1, 2)
>>>
The intent is to re-use the mock in subsequent tests but I suspect that, like a generator, it cannot be restarted.
So (better late than never) after being pointed in the right direction I looked in mock.py
and found that side_effect
is an iterator object (which cannot be reset once exhausted):
def __set_side_effect(self, value):
value = _try_iter(value)
...
def _try_iter(obj):
...
try:
return iter(obj)
except TypeError:
# XXXX backwards compatibility
# but this will blow up on first call - so maybe we should fail early?
return obj
and def reset_mock()
does not address the side efect.
Note that since Python 3.6, you can reset the mock side_effect
and return_value
with:
mock.reset_mock(return_value=True, side_effect=True)
From the docs:
In case you want to reset return_value or side_effect, then pass the corresponding parameter as True. Child mocks and the return value mock (if any) are reset as well.
As user2357112 commented, reassigning side_effect
will solve you problem.
>>> from mock import MagicMock
>>>
>>> lst = [1, 2]
>>> mock = MagicMock(side_effect=lst)
>>> mock(), mock()
(1, 2)
>>> mock.side_effect = lst # <-------
>>> mock(), mock()
(1, 2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With