Thin-wrapper around the mock package for easier use with py.test
Project description
This plugin installs a mocker fixture which is a thin-wrapper around the patching API provided by the excellent mock package, but with the benefit of not having to worry about undoing patches at the end of a test:
def test_unix_fs(mocker):
mocker.patch('os.remove')
UnixFS.rm('file')
os.remove.assert_called_once_with('file')
Usage
The mocker fixture has the same API as mock.patch, supporting the same arguments:
def test_foo(mocker):
# all valid calls
mocker.patch('os.remove')
mocker.patch.object(os, 'listdir', autospec=True)
mocked_isfile = mocker.patch('os.path.isfile')
The supported methods are:
mocker.patch: see http://www.voidspace.org.uk/python/mock/patch.html#patch.
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.
Note
Prior to version 0.4.0, the mocker fixture was named mock. This was changed because naming the fixture mock conflicts with the actual mock module, which made using it awkward when access to both the module and the plugin were required within a test.
The old fixture mock still works, but its use is discouraged and will be removed in version 1.0.
Requirements
Python 2.6+, Python 3.2+
pytest
mock (for Python < 3.3)
Install
Install using pip:
$ pip install pytest-mock
Changelog
Please consult releases.
Why bother with a plugin?
There are a number of different patch usages in the standard mock API, but IMHO they don’t scale very well when you have more than one or two patches to apply.
It may lead to an excessive nesting of with statements, breaking the flow of the test:
import mock
def test_unix_fs():
with mock.patch('os.remove'):
UnixFS.rm('file')
os.remove.assert_called_once_with('file')
with mock.patch('os.listdir'):
assert UnixFS.ls('dir') == expected
# ...
with mock.patch('shutil.copy'):
UnixFS.cp('src', 'dst')
# ...
One can use patch as a decorator to improve the flow of the test:
@mock.patch('os.remove')
@mock.patch('os.listdir')
@mock.patch('shutil.copy')
def test_unix_fs(mocked_copy, mocked_listdir, mocked_remove):
UnixFS.rm('file')
os.remove.assert_called_once_with('file')
assert UnixFS.ls('dir') == expected
# ...
UnixFS.cp('src', 'dst')
# ...
But this poses a few disadvantages:
test functions must receive the mock objects as parameter, even if you don’t plan to access them directly; also, order depends on the order of the decorated patch functions;
receiving the mocks as parameters doesn’t mix nicely with pytest’s approach of naming fixtures as parameters, or pytest.mark.parametrize;
you can’t easily undo the mocking during the test execution;
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.