Skip to content

Commit

Permalink
Fix #178: handle spy on async functions
Browse files Browse the repository at this point in the history
  • Loading branch information
frankie567 committed Jan 25, 2020
1 parent 2abec3b commit 06d1848
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 3 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
description="Thin-wrapper around the mock package for easier use with pytest",
long_description=open("README.rst", encoding="utf-8").read(),
keywords="pytest mock",
extras_require={"dev": ["pre-commit", "tox"]},
extras_require={"dev": ["pre-commit", "tox", "pytest-asyncio"]},
classifiers=[
"Development Status :: 5 - Production/Stable",
"Framework :: Pytest",
Expand Down
21 changes: 19 additions & 2 deletions src/pytest_mock/plugin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import functools
import inspect

Expand Down Expand Up @@ -96,7 +97,6 @@ def spy(self, obj, name):
if isinstance(value, (classmethod, staticmethod)):
autospec = False

@functools.wraps(method)
def wrapper(*args, **kwargs):
spy_obj.spy_return = None
spy_obj.spy_exception = None
Expand All @@ -109,7 +109,24 @@ def wrapper(*args, **kwargs):
spy_obj.spy_return = r
return r

spy_obj = self.patch.object(obj, name, side_effect=wrapper, autospec=autospec)
async def async_wrapper(*args, **kwargs):
spy_obj.spy_return = None
spy_obj.spy_exception = None
try:
r = await method(*args, **kwargs)
except Exception as e:
spy_obj.spy_exception = e
raise
else:
spy_obj.spy_return = r
return r

if asyncio.iscoroutinefunction(method):
wrapped = functools.update_wrapper(async_wrapper, method)
else:
wrapped = functools.update_wrapper(wrapper, method)

spy_obj = self.patch.object(obj, name, side_effect=wrapped, autospec=autospec)
spy_obj.spy_return = None
spy_obj.spy_exception = None
return spy_obj
Expand Down
15 changes: 15 additions & 0 deletions tests/test_pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,21 @@ def __call__(self, x):
assert spy.spy_return == 20


@pytest.mark.asyncio
async def test_instance_async_method_spy(mocker):
class Foo:
async def bar(self, arg):
return arg * 2

foo = Foo()
spy = mocker.spy(foo, "bar")

result = await foo.bar(10)

spy.assert_called_once_with(10)
assert result == 20


@contextmanager
def assert_traceback():
"""
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ envlist = py{35,36,37,38}, linting, norewrite
passenv = USER USERNAME
deps =
coverage
pytest-asyncio
commands =
coverage run --append --source={envsitepackagesdir}/pytest_mock -m pytest tests

Expand Down

0 comments on commit 06d1848

Please sign in to comment.