From 4faf92ae233afadac3831ab570531e540dc87830 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 21 Mar 2024 18:52:51 -0300 Subject: [PATCH] Fix regression with mocker.patch not being undone correctly The problem was introduced due to a bug in #417 which escaped review: we should always add a mock object to the cache, even if a similar one already exists. Fix #420 --- CHANGELOG.rst | 2 ++ src/pytest_mock/plugin.py | 7 ++----- tests/test_pytest_mock.py | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c16eed8..eba2dc4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,8 @@ UNRELEASED * `#415 `_: ``MockType`` and ``AsyncMockType`` can be imported from ``pytest_mock`` for type annotation purposes. +* `#420 `_: Fixed a regression which would cause ``mocker.patch.object`` to not being properly cleared between tests. + 3.13.0 (2024-03-21) ------------------- diff --git a/src/pytest_mock/plugin.py b/src/pytest_mock/plugin.py index 0d1e188..05f3530 100644 --- a/src/pytest_mock/plugin.py +++ b/src/pytest_mock/plugin.py @@ -60,11 +60,8 @@ def find(self, mock: MockType) -> MockCacheItem: return the_mock def add(self, mock: MockType, **kwargs: Any) -> MockCacheItem: - try: - return self.find(mock) - except ValueError: - self.cache.append(MockCacheItem(mock=mock, **kwargs)) - return self.cache[-1] + self.cache.append(MockCacheItem(mock=mock, **kwargs)) + return self.cache[-1] def remove(self, mock: MockType) -> None: mock_item = self.find(mock) diff --git a/tests/test_pytest_mock.py b/tests/test_pytest_mock.py index 61b75d8..fc16490 100644 --- a/tests/test_pytest_mock.py +++ b/tests/test_pytest_mock.py @@ -1264,3 +1264,28 @@ def foo(self): mocker.stop(spy) assert un_spy.foo() == 42 assert spy.call_count == 1 + + +def test_stop_multiple_patches(mocker: MockerFixture) -> None: + """Regression for #420.""" + + class Class1: + @staticmethod + def get(): + return 1 + + class Class2: + @staticmethod + def get(): + return 2 + + def handle_get(): + return 3 + + mocker.patch.object(Class1, "get", handle_get) + mocker.patch.object(Class2, "get", handle_get) + + mocker.stopall() + + assert Class1.get() == 1 + assert Class2.get() == 2