Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Releases
Unreleased
----------

* Fixed async mock assertion introspection to use awaited arguments instead of the latest call's arguments.
Comment thread
nicoddemus marked this conversation as resolved.
Resolved

* `#606 <https://github.com/pytest-dev/pytest-mock/pull/606>`_: ``mocker.resetall(return_value=True, side_effect=True)`` now also applies to non-callable mocks, such as those returned by ``mocker.create_autospec(SomeClass, instance=True)``. Previously both arguments were silently ignored for them.
* `#547 <https://github.com/pytest-dev/pytest-mock/issues/547>`_: Added ``SpyType`` for annotating ``mocker.spy`` results.
* Dropped support for EOL Python 3.9.
Expand Down
9 changes: 7 additions & 2 deletions src/pytest_mock/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,13 @@ def assert_wrapper(
else:
__mock_self = args[0]
msg = str(e)
if __mock_self.call_args is not None:
actual_args, actual_kwargs = __mock_self.call_args
call_args = (
__mock_self.await_args
if "await" in __wrapped_mock_method__.__name__

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking if the wrapper has "await" in the name works, but is a bit implicit... there are ways to make this a bit more explicit, but they are a bit more involved. This is good for now. 👍

else __mock_self.call_args
)
if call_args is not None:
actual_args, actual_kwargs = call_args
introspection = ""
try:
assert actual_args == args[1:]
Expand Down
35 changes: 35 additions & 0 deletions tests/test_pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,41 @@ def test_assert_has_calls(mocker: MockerFixture) -> None:
stub.assert_has_calls([mocker.call("bar")])


@pytest.mark.usefixtures("needs_assert_rewrite")
@pytest.mark.parametrize(
"assertion", ["assert_awaited_with", "assert_awaited_once_with", "assert_any_await"]
)
@pytest.mark.asyncio
async def test_async_assertion_uses_await_arguments(
mocker: MockerFixture, assertion: str
) -> None:
stub = mocker.AsyncMock()
await stub("awaited", source="awaited")
stub("called", source="called").close()

getattr(stub, assertion)("awaited", source="awaited")
with pytest.raises(AssertionError) as exc_info:
getattr(stub, assertion)("wrong", source="wrong")
introspection = str(exc_info.value).split("pytest introspection follows:")[1]
assert "'awaited'" in introspection
assert "'called'" not in introspection

with pytest.raises(AssertionError) as exc_info:
stub.assert_called_with("wrong", source="wrong")
introspection = str(exc_info.value).split("pytest introspection follows:")[1]
assert "'called'" in introspection
assert "'awaited'" not in introspection


@pytest.mark.usefixtures("needs_assert_rewrite")
def test_async_assertion_without_await(mocker: MockerFixture) -> None:
stub = mocker.AsyncMock()
stub("called").close()
with pytest.raises(AssertionError) as exc_info:
stub.assert_awaited_with("expected")
assert "pytest introspection follows:" not in str(exc_info.value)


def test_assert_has_calls_multiple_calls(mocker: MockerFixture) -> None:
stub = mocker.stub()
stub("foo")
Expand Down
Loading