Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge pull request #179 from frankie567/issue-178 #179

Merged
merged 3 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ jobs:
deploy:

if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')

runs-on: ubuntu-latest

needs: [build, linting]


steps:
- uses: actions/checkout@v1
- name: Set up Python
Expand All @@ -75,7 +76,6 @@ jobs:
run: |
python setup.py sdist bdist_wheel
- name: Publish package to PyPI
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
3.0.0 (UNRELEASED)
------------------

* Python 2.7 and 3.4 are no longer supported. Users using ``pip 9`` or later will install
a compatible version automatically.

* ``mocker.spy`` now also works with ``async def`` functions (`#179`_). Thanks `@frankie567`_ for the PR!

.. _#179: https://github.com/pytest-dev/pytest-mock/issues/179
.. _@frankie567: https://github.com/frankie567

2.0.0 (2020-01-04)
------------------

Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ In addition, spy objects contain two extra attributes:

``mocker.spy`` also works for class and static methods.

As of version 3.0.0, ``mocker.spy`` also works with ``async def`` functions.

.. note::

In versions earlier than ``2.0``, the attributes were called ``return_value`` and
Expand Down
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