What is the difference between the following two tests? (if any)
** in python 3.10
import unittest
from unittest.mock import Mock, patch
class Potato(object):
def spam(self, n):
return self.foo(n=n)
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(unittest.TestCase):
def test_side_effect(self):
spud = Potato()
with patch.object(spud, 'foo', side_effect=spud.foo) as mock_foo:
forty_two = spud.spam(n=40)
mock_foo.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
def test_wraps(self):
spud = Potato()
with patch.object(spud, 'foo', wraps=spud.foo) as mock_foo:
forty_two = spud.spam(n=40)
mock_foo.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
One uses side_effect to preserve the original method while the other uses wraps to effectively do the same thing (or at least as far as I can tell).
a bit late to the party, here's what I found in python source code.
def _execute_mock_call(self, /, *args, **kwargs):
# separate from _increment_mock_call so that awaited functions are
# executed separately from their call, also AsyncMock overrides this method
effect = self.side_effect
if effect is not None:
if _is_exception(effect):
raise effect
elif not _callable(effect):
result = next(effect)
if _is_exception(result):
raise result
else:
result = effect(*args, **kwargs)
if result is not DEFAULT:
return result
if self._mock_return_value is not DEFAULT:
return self.return_value
if self._mock_wraps is not None:
return self._mock_wraps(*args, **kwargs)
return self.return_value
As can be seen from above, side_effect could just be an exception or an iterator that returns an exception. Where as wraps would just simply pass through.
IMO, use side_effect when you want to raise exceptions, use "wraps" when you're "spying" on the method.
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