Skip to content

Commit

Permalink
Merge pull request #5 from nicoddemus/deprecate-mock
Browse files Browse the repository at this point in the history
Deprecate mock in favor of mocker
  • Loading branch information
nicoddemus committed Sep 17, 2014
2 parents 3b2fd83 + 68f3da8 commit 8c92792
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 31 deletions.
37 changes: 24 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
pytest-mock
===========

This plugin installs a ``mock`` fixture which is a thin-wrapper around the patching API
This plugin installs a ``mocker`` fixture which is a thin-wrapper around the patching API
provided by the excellent `mock <http://pypi.python.org/pypi/mock>`_ package,
but with the benefit of not having to worry about undoing patches at the end
of a test:

.. code-block:: python
def test_unix_fs(mock):
mock.patch('os.remove')
def test_unix_fs(mocker):
mocker.patch('os.remove')
UnixFS.rm('file')
os.remove.assert_called_once_with('file')
Expand Down Expand Up @@ -40,27 +40,38 @@ of a test:
Usage
=====

The ``mock`` fixture has the same API as
The ``mocker`` fixture has the same API as
`mock.patch <http://www.voidspace.org.uk/python/mock/patch.html#patch-decorators>`_,
supporting the same arguments:

.. code-block:: python
def test_foo(mock):
def test_foo(mocker):
# all valid calls
mock.patch('os.remove')
mock.patch.object(os, 'listdir', autospec=True)
mocked = mock.patch('os.path.isfile')
mocker.patch('os.remove')
mocker.patch.object(os, 'listdir', autospec=True)
mocked_isfile = mocker.patch('os.path.isfile')
The supported methods are:

* ``mock.patch``: see http://www.voidspace.org.uk/python/mock/patch.html#patch.
* ``mock.patch.object``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-object.
* ``mock.patch.multiple``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-multiple.
* ``mock.patch.dict``: see http://www.voidspace.org.uk/python/mock/patch.html#patch-dict.
* ``mock.stopall()``: stops all active patches at this point.
* ``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
============

Expand Down
16 changes: 14 additions & 2 deletions pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,23 @@ def __call__(self, *args, **kwargs):


@pytest.yield_fixture
def mock():
def mocker():
"""
return an object that has the same interface to the `mock` module, but
takes care of automatically undoing all patches after each test method.
"""
result = MockFixture()
yield result
result.stopall()
result.stopall()


@pytest.yield_fixture
def mock():
"""
Same as "mocker", but kept only for backward compatibility.
"""
import warnings
warnings.warn('"mock" fixture has been deprecated, use "mocker" instead',
DeprecationWarning)
for m in mocker():
yield m
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

setup(
name='pytest-mock',
version='0.3.0',
version='0.4.0',
entry_points={
'pytest11': ['pytest-mock = pytest_mock'],
},
Expand Down
52 changes: 37 additions & 15 deletions test_pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import pytest


pytest_plugins = 'pytester'

class UnixFS(object):
"""
Wrapper to os functions to simulate a Unix file system, used for testing
Expand All @@ -19,7 +21,7 @@ def ls(cls, path):


@pytest.fixture
def check_unix_fs_mocked(tmpdir, mock):
def check_unix_fs_mocked(tmpdir, mocker):
"""
performs a standard test in a UnixFS, assuming that both `os.remove` and
`os.listdir` have been mocked previously.
Expand All @@ -40,7 +42,7 @@ def check(mocked_rm, mocked_ls):
assert UnixFS.ls(str(tmpdir)) == ['bar.txt']
mocked_ls.assert_called_once_with(str(tmpdir))

mock.stopall()
mocker.stopall()

assert UnixFS.ls(str(tmpdir)) == ['foo.txt']
UnixFS.rm(str(file_name))
Expand All @@ -49,43 +51,63 @@ def check(mocked_rm, mocked_ls):
return check


def mock_using_patch_object(mock):
return mock.patch.object(os, 'remove'), mock.patch.object(os, 'listdir')
def mock_using_patch_object(mocker):
return mocker.patch.object(os, 'remove'), mocker.patch.object(os, 'listdir')


def mock_using_patch(mock):
return mock.patch('os.remove'), mock.patch('os.listdir')
def mock_using_patch(mocker):
return mocker.patch('os.remove'), mocker.patch('os.listdir')


def mock_using_patch_multiple(mock):
def mock_using_patch_multiple(mocker):
from pytest_mock import mock_module

r = mock.patch.multiple('os', remove=mock_module.DEFAULT,
listdir=mock_module.DEFAULT)
r = mocker.patch.multiple('os', remove=mock_module.DEFAULT,
listdir=mock_module.DEFAULT)
return r['remove'], r['listdir']


@pytest.mark.parametrize('mock_fs', [mock_using_patch_object, mock_using_patch,
mock_using_patch_multiple],
)
def test_mock_patches(mock_fs, mock, check_unix_fs_mocked):
def test_mock_patches(mock_fs, mocker, check_unix_fs_mocked):
"""
Installs mocks into `os` functions and performs a standard testing of
mock functionality. We parametrize different mock methods to ensure
all (intended, at least) mock API is covered.
"""
mock_fs(mock)
mocked_rm, mocked_ls = mock_fs(mock)
# mock it twice on purpose to ensure we unmock it correctly later
mock_fs(mocker)
mocked_rm, mocked_ls = mock_fs(mocker)
check_unix_fs_mocked(mocked_rm, mocked_ls)


def test_mock_patch_dict(mock):
def test_mock_patch_dict(mocker):
"""
Testing
:param mock:
"""
x = {'original': 1}
mock.patch.dict(x, values=[('new', 10)], clear=True)
mocker.patch.dict(x, values=[('new', 10)], clear=True)
assert x == {'new': 10}
mock.stopall()
mocker.stopall()
assert x == {'original': 1}


def test_mock_fixture_is_deprecated(testdir):
"""
Test that a warning emitted when using deprecated "mock" fixture.
"""
testdir.makepyfile('''
import warnings
import os
warnings.simplefilter('always')
def test_foo(mock, tmpdir):
mock.patch('os.listdir', return_value=['mocked'])
assert os.listdir(str(tmpdir)) == ['mocked']
mock.stopall()
assert os.listdir(str(tmpdir)) == []
''')
result = testdir.runpytest('-s')
result.stderr.fnmatch_lines(['*"mock" fixture has been deprecated*'])

0 comments on commit 8c92792

Please sign in to comment.