merge
This commit is contained in:
commit
b582c923ba
|
@ -440,11 +440,16 @@ Classes and functions
|
|||
locals dictionary of the given frame.
|
||||
|
||||
|
||||
.. function:: formatargspec(args[, varargs, varkw, defaults, formatarg, formatvarargs, formatvarkw, formatvalue])
|
||||
.. function:: formatargspec(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations])
|
||||
|
||||
Format a pretty argument spec from the four values returned by
|
||||
:func:`getargspec`. The format\* arguments are the corresponding optional
|
||||
formatting functions that are called to turn names and values into strings.
|
||||
Format a pretty argument spec from the values returned by
|
||||
:func:`getargspec` or :func:`getfullargspec`.
|
||||
|
||||
The first seven arguments are (``args``, ``varargs``, ``varkw``,
|
||||
``defaults``, ``kwonlyargs``, ``kwonlydefaults``, ``annotations``). The
|
||||
other five arguments are the corresponding optional formatting functions
|
||||
that are called to turn names and values into strings. The last argument
|
||||
is an optional function to format the sequence of arguments.
|
||||
|
||||
|
||||
.. function:: formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue])
|
||||
|
|
|
@ -838,56 +838,6 @@ and the `return_value` will use your subclass automatically. That means all
|
|||
children of a `CopyingMock` will also have the type `CopyingMock`.
|
||||
|
||||
|
||||
Multiple calls with different effects
|
||||
-------------------------------------
|
||||
|
||||
Handling code that needs to behave differently on subsequent calls during the
|
||||
test can be tricky. For example you may have a function that needs to raise
|
||||
an exception the first time it is called but returns a response on the second
|
||||
call (testing retry behaviour).
|
||||
|
||||
One approach is to use a :attr:`side_effect` function that replaces itself. The
|
||||
first time it is called the `side_effect` sets a new `side_effect` that will
|
||||
be used for the second call. It then raises an exception:
|
||||
|
||||
>>> def side_effect(*args):
|
||||
... def second_call(*args):
|
||||
... return 'response'
|
||||
... mock.side_effect = second_call
|
||||
... raise Exception('boom')
|
||||
...
|
||||
>>> mock = Mock(side_effect=side_effect)
|
||||
>>> mock('first')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
Exception: boom
|
||||
>>> mock('second')
|
||||
'response'
|
||||
>>> mock.assert_called_with('second')
|
||||
|
||||
Another perfectly valid way would be to pop return values from a list. If the
|
||||
return value is an exception, raise it instead of returning it:
|
||||
|
||||
>>> returns = [Exception('boom'), 'response']
|
||||
>>> def side_effect(*args):
|
||||
... result = returns.pop(0)
|
||||
... if isinstance(result, Exception):
|
||||
... raise result
|
||||
... return result
|
||||
...
|
||||
>>> mock = Mock(side_effect=side_effect)
|
||||
>>> mock('first')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
Exception: boom
|
||||
>>> mock('second')
|
||||
'response'
|
||||
>>> mock.assert_called_with('second')
|
||||
|
||||
Which approach you prefer is a matter of taste. The first approach is actually
|
||||
a line shorter but maybe the second approach is more readable.
|
||||
|
||||
|
||||
Nesting Patches
|
||||
---------------
|
||||
|
||||
|
|
|
@ -823,6 +823,20 @@ a `StopIteration` is raised):
|
|||
...
|
||||
StopIteration
|
||||
|
||||
If any members of the iterable are exceptions they will be raised instead of
|
||||
returned::
|
||||
|
||||
>>> iterable = (33, ValueError, 66)
|
||||
>>> m = MagicMock(side_effect=iterable)
|
||||
>>> m()
|
||||
33
|
||||
>>> m()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError
|
||||
>>> m()
|
||||
66
|
||||
|
||||
|
||||
.. _deleting-attributes:
|
||||
|
||||
|
|
|
@ -78,11 +78,14 @@ def _getsignature(func, skipfirst, instance=False):
|
|||
return
|
||||
|
||||
try:
|
||||
regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
|
||||
argspec = inspect.getfullargspec(func)
|
||||
except TypeError:
|
||||
# C function / method, possibly inherited object().__init__
|
||||
return
|
||||
|
||||
regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec
|
||||
|
||||
|
||||
# instance methods and classmethods need to lose the self argument
|
||||
if getattr(func, '__self__', None) is not None:
|
||||
regargs = regargs[1:]
|
||||
|
@ -90,8 +93,9 @@ def _getsignature(func, skipfirst, instance=False):
|
|||
# this condition and the above one are never both True - why?
|
||||
regargs = regargs[1:]
|
||||
|
||||
signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults,
|
||||
formatvalue=lambda value: "")
|
||||
signature = inspect.formatargspec(
|
||||
regargs, varargs, varkw, defaults,
|
||||
kwonly, kwonlydef, ann, formatvalue=lambda value: "")
|
||||
return signature[1:-1], func
|
||||
|
||||
|
||||
|
@ -891,7 +895,10 @@ class CallableMixin(Base):
|
|||
raise effect
|
||||
|
||||
if not _callable(effect):
|
||||
return next(effect)
|
||||
result = next(effect)
|
||||
if _is_exception(result):
|
||||
raise result
|
||||
return result
|
||||
|
||||
ret_val = effect(*args, **kwargs)
|
||||
if ret_val is DEFAULT:
|
||||
|
@ -931,8 +938,9 @@ class Mock(CallableMixin, NonCallableMock):
|
|||
arguments as the mock, and unless it returns `DEFAULT`, the return
|
||||
value of this function is used as the return value.
|
||||
|
||||
Alternatively `side_effect` can be an exception class or instance. In
|
||||
this case the exception will be raised when the mock is called.
|
||||
If `side_effect` is an iterable then each call to the mock will return
|
||||
the next value from the iterable. If any of the members of the iterable
|
||||
are exceptions they will be raised instead of returned.
|
||||
|
||||
If `side_effect` is an iterable then each call to the mock will return
|
||||
the next value from the iterable.
|
||||
|
|
|
@ -367,7 +367,7 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
|
||||
|
||||
def test_create_autospec_unbound_methods(self):
|
||||
# see issue 128
|
||||
# see mock issue 128
|
||||
# this is expected to fail until the issue is fixed
|
||||
return
|
||||
class Foo(object):
|
||||
|
@ -391,6 +391,19 @@ class SpecSignatureTest(unittest.TestCase):
|
|||
self.assertEqual(m.a, '3')
|
||||
|
||||
|
||||
def test_create_autospec_keyword_only_arguments(self):
|
||||
def foo(a, *, b=None):
|
||||
pass
|
||||
|
||||
m = create_autospec(foo)
|
||||
m(1)
|
||||
m.assert_called_with(1)
|
||||
self.assertRaises(TypeError, m, 1, 2)
|
||||
|
||||
m(2, b=3)
|
||||
m.assert_called_with(2, b=3)
|
||||
|
||||
|
||||
def test_function_as_instance_attribute(self):
|
||||
obj = SomeClass()
|
||||
def f(a):
|
||||
|
|
|
@ -868,6 +868,16 @@ class MockTest(unittest.TestCase):
|
|||
self.assertRaises(StopIteration, mock)
|
||||
|
||||
|
||||
def test_side_effect_iterator_exceptions(self):
|
||||
for Klass in Mock, MagicMock:
|
||||
iterable = (ValueError, 3, KeyError, 6)
|
||||
m = Klass(side_effect=iterable)
|
||||
self.assertRaises(ValueError, m)
|
||||
self.assertEqual(m(), 3)
|
||||
self.assertRaises(KeyError, m)
|
||||
self.assertEqual(m(), 6)
|
||||
|
||||
|
||||
def test_side_effect_setting_iterator(self):
|
||||
mock = Mock()
|
||||
mock.side_effect = iter([1, 2, 3])
|
||||
|
|
Loading…
Reference in New Issue