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鈥檒l 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
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
@@ -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
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
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
@@ -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
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
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