diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0592b5d..a83c5d8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,9 @@ +0.9.0 +----- + +* New ``mocker.resetall`` function, which calls ``reset_mock()`` in all mocked + objects up to that point. Thanks to `@mathrick`_ for the PR! + 0.8.1 ----- @@ -80,6 +86,7 @@ First release. .. _#2: https://github.com/pytest-dev/pytest-qt/issues/2 +.. _@mathrick: https://github.com/mathrick .. _@tigarmo: https://github.com/tigarmo .. _@rouge8: https://github.com/rouge8 .. _@fogo: https://github.com/fogo diff --git a/README.rst b/README.rst index 3b86b81..eb44384 100644 --- a/README.rst +++ b/README.rst @@ -57,7 +57,8 @@ The supported methods are: * ``mocker.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object. * ``mocker.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple. * ``mocker.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict. -* ``mocker.stopall()``: stops all active patches at this point. +* ``mocker.stopall()``: stops all active patches up to this point. +* ``mocker.resetall()``: calls ``reset_mock()`` in all mocked objects up to this point. *New in version 0.9* Note that, although mocker's API is intentionally the same as ``mock.patch``'s, its uses as context managers and function decorators are **not** supported. The purpose of this plugin is to make the use of context managers and function decorators for mocking unnecessary. Indeed, trying to use the functionality in ``mocker`` in this manner can lead to non-intuitive errors: diff --git a/pytest_mock.py b/pytest_mock.py index 15ae609..2e072b7 100644 --- a/pytest_mock.py +++ b/pytest_mock.py @@ -22,7 +22,15 @@ class MockFixture(object): def __init__(self): self._patches = [] # list of mock._patch objects - self.patch = self._Patcher(self._patches) + self._mocks = [] # list of MagicMock objects + self.patch = self._Patcher(self._patches, self._mocks) + + def resetall(self): + """ + Call reset_mock() on all patchers started by this fixture. + """ + for m in self._mocks: + m.reset_mock() def stopall(self): """ @@ -32,6 +40,7 @@ def stopall(self): for p in reversed(self._patches): p.stop() self._patches[:] = [] + self._mocks[:] = [] def spy(self, obj, name): """ @@ -75,8 +84,9 @@ class _Patcher(object): etc. We need this indirection to keep the same API of the mock package. """ - def __init__(self, patches): + def __init__(self, patches, mocks): self._patches = patches + self._mocks = mocks def _start_patch(self, mock_func, *args, **kwargs): """Patches something by calling the given function from the mock @@ -86,6 +96,7 @@ def _start_patch(self, mock_func, *args, **kwargs): p = mock_func(*args, **kwargs) mocked = p.start() self._patches.append(p) + self._mocks.append(mocked) return mocked def object(self, *args, **kwargs): diff --git a/test_pytest_mock.py b/test_pytest_mock.py index 61a203c..23868b8 100644 --- a/test_pytest_mock.py +++ b/test_pytest_mock.py @@ -143,6 +143,21 @@ def test_mocker_has_mock_class_as_attribute_for_instantiation(): assert isinstance(mocker.Mock(), mock_module.Mock) +def test_mocker_resetall(mocker): + listdir = mocker.patch('os.listdir') + open = mocker.patch('os.open') + + listdir("/tmp") + open("/tmp/foo.txt") + listdir.assert_called_once_with("/tmp") + open.assert_called_once_with("/tmp/foo.txt") + + mocker.resetall() + + assert not listdir.called + assert not open.called + + def test_mocker_stub(mocker): def foo(on_something): on_something('foo', 'bar')