From 1e6e094a3bb19bd53660c39eee4ed37a7c71622b Mon Sep 17 00:00:00 2001 From: oyeong011 Date: Tue, 8 Sep 2026 11:49:25 +0900 Subject: [PATCH] Preserve assertion failures for keyword call expectations Confidence: high Scope-risk: narrow Tested: Regression fails before fix and passes after; full suite results recorded externally Not-tested: Other operating systems and Python versions --- CHANGELOG.rst | 2 ++ src/pytest_mock/plugin.py | 2 +- tests/test_pytest_mock.py | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 46d1677..d30bbd1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,8 @@ Releases Unreleased ---------- +* Preserve assertion failures when ``assert_has_calls`` receives ``calls`` as a keyword. + * `#547 `_: Added ``SpyType`` for annotating ``mocker.spy`` results. * Dropped support for EOL Python 3.9. * `#147 `_: Removed handling of ``RuntimeError: stop called on unstarted patcher``, which can no longer occur in the supported Python versions. diff --git a/src/pytest_mock/plugin.py b/src/pytest_mock/plugin.py index df63fb4..d971357 100644 --- a/src/pytest_mock/plugin.py +++ b/src/pytest_mock/plugin.py @@ -537,7 +537,7 @@ def assert_has_calls_wrapper( msg = str(e) if __mock_self.call_args_list is not None: actual_calls = list(__mock_self.call_args_list) - expect_calls = args[1] + expect_calls = args[1] if len(args) > 1 else kwargs["calls"] introspection = "" from itertools import zip_longest diff --git a/tests/test_pytest_mock.py b/tests/test_pytest_mock.py index c497aea..4e05520 100644 --- a/tests/test_pytest_mock.py +++ b/tests/test_pytest_mock.py @@ -1428,3 +1428,10 @@ def handle_get(): assert Class1.get() == 1 assert Class2.get() == 2 + + +def test_assert_has_calls_keyword(mocker: MockerFixture) -> None: + stub = mocker.stub() + stub("actual") + with pytest.raises(AssertionError): + stub.assert_has_calls(calls=[mocker.call("expected")])