From 5257e3c0df0a18bca4028daa9e6d2d91870ff576 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 21 Mar 2024 19:06:27 -0300 Subject: [PATCH] Refactor MockCache to have a narrow interface It should also be responsible for stopping the patchers, instead of acting merely as storage. Follow up the previous commit. --- src/pytest_mock/plugin.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/pytest_mock/plugin.py b/src/pytest_mock/plugin.py index 05f3530..1e0a0b2 100644 --- a/src/pytest_mock/plugin.py +++ b/src/pytest_mock/plugin.py @@ -49,33 +49,37 @@ class MockCacheItem: @dataclass class MockCache: + """ + Cache MagicMock and Patcher instances so we can undo them later. + """ + cache: List[MockCacheItem] = field(default_factory=list) - def find(self, mock: MockType) -> MockCacheItem: - the_mock = next( - (mock_item for mock_item in self.cache if mock_item.mock == mock), None - ) - if the_mock is None: - raise ValueError("This mock object is not registered") - return the_mock + def _find(self, mock: MockType) -> MockCacheItem: + for mock_item in self.cache: + if mock_item.mock is mock: + return mock_item + raise ValueError("This mock object is not registered") def add(self, mock: MockType, **kwargs: Any) -> MockCacheItem: self.cache.append(MockCacheItem(mock=mock, **kwargs)) return self.cache[-1] def remove(self, mock: MockType) -> None: - mock_item = self.find(mock) + mock_item = self._find(mock) + if mock_item.patch: + mock_item.patch.stop() self.cache.remove(mock_item) def clear(self) -> None: + for mock_item in reversed(self.cache): + if mock_item.patch is not None: + mock_item.patch.stop() self.cache.clear() def __iter__(self) -> Iterator[MockCacheItem]: return iter(self.cache) - def __reversed__(self) -> Iterator[MockCacheItem]: - return reversed(self.cache) - class MockerFixture: """ @@ -146,9 +150,6 @@ def stopall(self) -> None: Stop all patchers started by this fixture. Can be safely called multiple times. """ - for mock_item in reversed(self._mock_cache): - if mock_item.patch is not None: - mock_item.patch.stop() self._mock_cache.clear() def stop(self, mock: unittest.mock.MagicMock) -> None: @@ -156,9 +157,6 @@ def stop(self, mock: unittest.mock.MagicMock) -> None: Stops a previous patch or spy call by passing the ``MagicMock`` object returned by it. """ - mock_item = self._mock_cache.find(mock) - if mock_item.patch: - mock_item.patch.stop() self._mock_cache.remove(mock) def spy(self, obj: object, name: str) -> MockType: