summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Foord <michael@voidspace.org.uk>2012-04-21 01:44:18 +0100
committerMichael Foord <michael@voidspace.org.uk>2012-04-21 01:44:18 +0100
commit72af501f32378e84af6f5407cab4a79d7ec453ac (patch)
tree51012cb32efce0f0b28ea20ce15a1f31a76ecc65
parent5daa4a0a673c122bd3ba8e7582bad2e02d141d8a (diff)
downloadmock-72af501f32378e84af6f5407cab4a79d7ec453ac.tar.gz
Exceptions in iterable side_effect will be raised
-rw-r--r--docs/changelog.txt2
-rw-r--r--docs/examples.txt5
-rw-r--r--docs/mock.txt19
-rw-r--r--mock.py9
-rw-r--r--tests/testmock.py10
5 files changed, 42 insertions, 3 deletions
diff --git a/docs/changelog.txt b/docs/changelog.txt
index 8b65457..ad16637 100644
--- a/docs/changelog.txt
+++ b/docs/changelog.txt
@@ -11,6 +11,8 @@ CHANGELOG
* `PropertyMock` attributes are now standard `MagicMocks`
* `create_autospec` works with attributes present in results of `dir` that
can't be fetched from the object's class. Contributed by Konstantine Rybnikov
+* Any exceptions in an iterable `side_effect` will be raised instead of
+ returned
2012/03/25 Version 1.0.0 alpha 1
diff --git a/docs/examples.txt b/docs/examples.txt
index d35dd45..d6a96fb 100644
--- a/docs/examples.txt
+++ b/docs/examples.txt
@@ -498,6 +498,11 @@ children of a `CopyingMock` will also have the type `CopyingMock`.
Multiple calls with different effects
=====================================
+.. note::
+
+ In mock 1.0 the handling of iterable `side_effect` was changed. Any
+ exceptions in the iterable will be raised instead of returned.
+
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
diff --git a/docs/mock.txt b/docs/mock.txt
index e5dcd60..58712b2 100644
--- a/docs/mock.txt
+++ b/docs/mock.txt
@@ -61,7 +61,8 @@ the `new_callable` argument to `patch`.
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.
+ the next value from the iterable. If any of the members of the iterable
+ are exceptions they will be raised instead of returned.
A `side_effect` can be cleared by setting it to `None`.
@@ -728,6 +729,22 @@ a `StopIteration` is raised):
...
StopIteration
+If any members of the iterable are exceptions they will be raised instead of
+returned:
+
+.. doctest::
+
+ >>> iterable = (33, ValueError, 66)
+ >>> m = MagicMock(side_effect=iterable)
+ >>> m()
+ 33
+ >>> m()
+ Traceback (most recent call last):
+ ...
+ ValueError
+ >>> m()
+ 66
+
.. _deleting-attributes:
diff --git a/mock.py b/mock.py
index 6e9c18a..16f0fc8 100644
--- a/mock.py
+++ b/mock.py
@@ -981,8 +981,12 @@ class CallableMixin(Base):
if _is_exception(effect):
raise effect
+ ret_val = DEFAULT
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:
@@ -1026,7 +1030,8 @@ class Mock(CallableMixin, NonCallableMock):
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.
+ the next value from the iterable. If any of the members of the iterable
+ are exceptions they will be raised instead of returned.
* `return_value`: The value returned when the mock is called. By default
this is a new Mock (created on first access). See the
diff --git a/tests/testmock.py b/tests/testmock.py
index 1f3bdf9..f3ceea9 100644
--- a/tests/testmock.py
+++ b/tests/testmock.py
@@ -959,6 +959,16 @@ class MockTest(unittest2.TestCase):
self.assertIs(mock.side_effect, this_iter)
+ 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_assert_has_calls_any_order(self):
mock = Mock()
mock(1, 2)