Skip to main content

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 mock package, but with the benefit of not having to worry about undoing patches at the end of a test:

import os

class UnixFS:

    def rm(filename):

def test_unix_fs(mocker):

python version anaconda ci appveyor coverage black


The mocker fixture has the same API as mock.patch, supporting the same arguments:

def test_foo(mocker):
    # all valid calls
    mocker.patch.object(os, 'listdir', autospec=True)
    mocked_isfile = mocker.patch('os.path.isfile')

The supported methods are:

These objects from the mock module are accessible directly from mocker for convenience:


The spy acts exactly like the original method in all cases, except it allows use of mock features with it, like retrieving call count. It also works for class and static methods.

def test_spy(mocker):
    class Foo(object):
        def bar(self):
            return 42

    foo = Foo()
    mocker.spy(foo, 'bar')
    assert == 42
    assert == 1


The stub is a mock object that accepts any arguments and is useful to test callbacks, for instance. May be passed a name to be used by the constructed stub object in its repr (useful for debugging).

def test_stub(mocker):
    def foo(on_something):
        on_something('foo', 'bar')

    stub = mocker.stub(name='on_something_stub')

    stub.assert_called_once_with('foo', 'bar')

Improved reporting of mock call assertion errors

This plugin monkeypatches the mock library to improve pytest output for failures of mock call assertions like Mock.assert_called_with() by hiding internal traceback entries from the mock module.

It also adds introspection information on differing call arguments when calling the helper methods. This features catches AssertionError raised in the method, and uses py.test’s own advanced assertions to return a better diff:

mocker = <pytest_mock.MockFixture object at 0x0381E2D0>

    def test(mocker):
        m = mocker.Mock()
>       m.assert_called_once_with('', bar=4)
E       AssertionError: Expected call: mock('', bar=4)
E       Actual call: mock('fo')
E       pytest introspection follows:
E       Args:
E       assert ('fo',) == ('',)
E         At index 0 diff: 'fo' != ''
E         Use -v to get the full diff
E       Kwargs:
E       assert {} == {'bar': 4}
E         Right contains more items:
E         {'bar': 4}
E         Use -v to get the full diff AssertionError
========================== 1 failed in 0.03 seconds ===========================

This is useful when asserting mock calls with many/nested arguments and trying to quickly see the difference.

This feature is probably safe, but if you encounter any problems it can be disabled in your pytest.ini file:

mock_traceback_monkeypatch = false

Note that this feature is automatically disabled with the --tb=native option. The underlying mechanism used to suppress traceback entries from mock module does not work with that option anyway plus it generates confusing messages on Python 3.5 due to exception chaining

Use standalone “mock” package

New in version 1.4.0.

Python 3 users might want to use a newest version of the mock package as published on PyPI than the one that comes with the Python distribution.

mock_use_standalone_module = true

This will force the plugin to import mock instead of the unittest.mock module bundled with Python 3.4+. Note that this option is only used in Python 3+, as Python 2 users only have the option to use the mock package from PyPI anyway.


  • Python 2.7, Python 3.4+
  • pytest
  • mock (for Python 2)


Install using pip:

$ pip install pytest-mock


Please consult the changelog page.

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'):

        with mock.patch('os.listdir'):
            assert'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:

def test_unix_fs(mocked_copy, mocked_listdir, mocked_remove):

    assert'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;

Note about usage as context manager

Although mocker’s API is intentionally the same as mock.patch’s, its use as context manager and function decorator is not supported through the fixture. 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:

def test_context_manager(mocker):
    a = A()
    with mocker.patch.object(a, 'doIt', return_value=True, autospec=True):
        assert a.doIt() == True
================================== FAILURES ===================================
____________________________ test_context_manager _____________________________
in test_context_manager
    with mocker.patch.object(a, 'doIt', return_value=True, autospec=True):
E   AttributeError: __exit__

You can however use mocker.mock_module to access the underlying mock module, e.g. to return a context manager in a fixture that mocks something temporarily:

def fixture_cm(mocker):
    def my_cm():
        def mocked():

        with mocker.mock_module.patch.object(SomeClass, 'method', mocked):
    return my_cm


Contributions are welcome! After cloning the repository, create a virtual env and install pytest-mock in editable mode with dev extras:

$ pip install --editable .[dev]
$ pre-commit install

Tests are run with tox, you can run the baseline environments before submitting a PR:

$ tox -e py27,py36,linting

Style checks and formatting are done automatically during commit courtesy of pre-commit.


Distributed under the terms of the MIT license.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, size & hash SHA256 hash help File type Python version Upload date
pytest_mock-1.10.1-py2.py3-none-any.whl (9.5 kB) Copy SHA256 hash SHA256 Wheel py2.py3
pytest-mock-1.10.1.tar.gz (22.1 kB) Copy SHA256 hash SHA256 Source None

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN SignalFx SignalFx Supporter DigiCert DigiCert EV certificate StatusPage StatusPage Status page