Skip to content

Commit

Permalink
mocker.spy now also tracks return value
Browse files Browse the repository at this point in the history
Related to pytest-dev#118
  • Loading branch information
nicoddemus committed Sep 28, 2019
1 parent 58b5048 commit 611fe79
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 3 deletions.
6 changes: 6 additions & 0 deletions 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
------

Expand Down
6 changes: 4 additions & 2 deletions README.rst
Expand Up @@ -88,10 +88,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):
Expand All @@ -104,6 +103,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
----

Expand Down
9 changes: 8 additions & 1 deletion pytest_mock.py
Expand Up @@ -2,6 +2,7 @@

import inspect
import sys
from functools import wraps

import pytest

Expand Down Expand Up @@ -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):
Expand Down
13 changes: 13 additions & 0 deletions test_pytest_mock.py
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 611fe79

Please sign in to comment.