diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a451509..eec73cb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,9 @@ +1.11.0 +------ + +* The object returned by ``mocker.spy`` now also tracks the return value + of the spied method/function. + 1.10.4 ------ diff --git a/README.rst b/README.rst index 4ce4d39..3b2c587 100644 --- a/README.rst +++ b/README.rst @@ -85,10 +85,9 @@ These objects from the ``mock`` module are accessible directly from ``mocker`` f Spy --- -The spy acts exactly like the original method in all cases, except it allows use of `mock` +The spy acts exactly like the original method in all cases, except it allows use of ``mock`` features with it, like retrieving call count. It also works for class and static methods. - .. code-block:: python def test_spy(mocker): @@ -101,6 +100,9 @@ features with it, like retrieving call count. It also works for class and static assert foo.bar() == 42 assert foo.bar.call_count == 1 +Since version ``1.11``, it is also possible to query the ``return_value`` attribute +to observe what the spied function/method returned. + Stub ---- diff --git a/pytest_mock.py b/pytest_mock.py index 5c56eb9..7d41610 100644 --- a/pytest_mock.py +++ b/pytest_mock.py @@ -2,6 +2,7 @@ import inspect import sys +from functools import wraps import pytest @@ -104,7 +105,13 @@ def spy(self, obj, name): if isinstance(value, (classmethod, staticmethod)): autospec = False - result = self.patch.object(obj, name, side_effect=method, autospec=autospec) + @wraps(method) + def wrapper(*args, **kwargs): + r = method(*args, **kwargs) + result.return_value = r + return r + + result = self.patch.object(obj, name, side_effect=wrapper, autospec=autospec) return result def stub(self, name=None): diff --git a/test_pytest_mock.py b/test_pytest_mock.py index cdc04fe..4611aba 100644 --- a/test_pytest_mock.py +++ b/test_pytest_mock.py @@ -238,7 +238,9 @@ def bar(self, arg): assert foo.bar(arg=10) == 20 assert other.bar(arg=10) == 20 foo.bar.assert_called_once_with(arg=10) + assert foo.bar.return_value == 20 spy.assert_called_once_with(arg=10) + assert spy.return_value == 20 @skip_pypy @@ -272,6 +274,7 @@ class Foo(Base): assert other.bar(arg=10) == 20 calls = [mocker.call(foo, arg=10), mocker.call(other, arg=10)] assert spy.call_args_list == calls + assert spy.return_value == 20 @skip_pypy @@ -284,7 +287,9 @@ def bar(cls, arg): spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) + assert Foo.bar.return_value == 20 spy.assert_called_once_with(arg=10) + assert spy.return_value == 20 @skip_pypy @@ -301,7 +306,9 @@ class Foo(Base): spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) + assert Foo.bar.return_value == 20 spy.assert_called_once_with(arg=10) + assert spy.return_value == 20 @skip_pypy @@ -320,7 +327,9 @@ def bar(cls, arg): spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) + assert Foo.bar.return_value == 20 spy.assert_called_once_with(arg=10) + assert spy.return_value == 20 @skip_pypy @@ -333,7 +342,9 @@ def bar(arg): spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) + assert Foo.bar.return_value == 20 spy.assert_called_once_with(arg=10) + assert spy.return_value == 20 @skip_pypy @@ -350,7 +361,9 @@ class Foo(Base): spy = mocker.spy(Foo, "bar") assert Foo.bar(arg=10) == 20 Foo.bar.assert_called_once_with(arg=10) + assert Foo.bar.return_value == 20 spy.assert_called_once_with(arg=10) + assert spy.return_value == 20 @contextmanager