Skip to main content

This plugin provides a mocker fixture which is a thin-wrapper around the patching API provided by the mock package:

import os

class UnixFS:

    @staticmethod
    def rm(filename):
        os.remove(filename)

def test_unix_fs(mocker):
    mocker.patch('os.remove')
    UnixFS.rm('file')
    os.remove.assert_called_once_with('file')

Besides undoing the mocking automatically after the end of the test, it also provides other nice utilities such as spy and stub, and uses pytest introspection when comparing calls.

python version anaconda ci coverage black

Professionally supported pytest-mock is now available

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:

Also, as a convenience, these names from the mock module are accessible directly from mocker:

Spy

The mocker.spy object acts exactly like the original method in all cases, except the spy also tracks method calls, return values and exceptions raised.

def test_spy(mocker):
    class Foo(object):
        def bar(self, v):
            return v * 2

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

    spy.assert_called_once_with(21)
    assert spy.spy_return == 42

The object returned by mocker.spy is a MagicMock object, so all standard checking functions are available (like assert_called_once_with in the example above).

In addition, spy objects contain two extra attributes:

  • spy_return: contains the returned value of the spied function.

  • spy_exception: contain the last exception value raised by the spied function/method when it was last called, or None if no exception was raised.

mocker.spy also works for class and static methods.

Stub

The stub is a mock object that accepts any arguments and is useful to test callbacks. It may receive an optional name that is shown 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')

    foo(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('fo')
>       m.assert_called_once_with('', bar=4)
E       AssertionError: Expected call: mock('', bar=4)
E       Actual call: mock('fo')
E
E       pytest introspection follows:
E
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


test_foo.py:6: 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:

[pytest]
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.

[pytest]
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.

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:

def test_context_manager(mocker):
    a = A()
    with mocker.patch.object(a, 'doIt', return_value=True, autospec=True):  # DO NOT DO THIS
        assert a.doIt() == True

The purpose of this plugin is to make the use of context managers and function decorators for mocking unnecessary.

Requirements

  • Python 2.7, Python 3.4+

  • pytest

  • mock (for Python 2)

Install

Install using pip:

$ pip install pytest-mock

Changelog

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

An alternative is to use contextlib.ExitStack to stack the context managers in a single level of indentation to improve the flow of the test:

import contextlib
import mock

def test_unix_fs():
    with contextlib.ExitStack() as stack:
        stack.enter_context(mock.patch('os.remove'))
        UnixFS.rm('file')
        os.remove.assert_called_once_with('file')

        stack.enter_context(mock.patch('os.listdir'))
        assert UnixFS.ls('dir') == expected
        # ...

        stack.enter_context(mock.patch('shutil.copy'))
        UnixFS.cp('src', 'dst')
        # ...

But this is arguably a little more complex than using pytest-mock.

Contributing

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.

License

Distributed under the terms of the MIT license.

Security contact information

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Metadata

Release files for pytest-mock 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-mock 2.0.0
File Size Uploaded
pytest-mock-2.0.0.tar.gz 24.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-mock 2.0.0
File Interpreter ABI Platform
pytest_mock-2.0.0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 35.2 kB

Release files / pytest-mock-2.0.0.tar.gz

Download URL pytest-mock-2.0.0.tar.gz
Size 24.7 kB
Tags Source
SHA-256 checksum
How to use checksums
b35eb281e93aafed138db25c8772b95d3756108b601947f89af503f8c629413f
BLAKE2b-256 checksum
How to use checksums
e28bb9671ce133aed04838fdd37ef408bfdd402e81ad634beca1c6cd0b8a7524
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/44.0.0 requests-toolbelt/0.9.1 tqdm/4.41.1 CPython/3.7.6

Release files / pytest_mock-2.0.0-py2.py3-none-any.whl

Download URL pytest_mock-2.0.0-py2.py3-none-any.whl
Size 10.6 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
cb67402d87d5f53c579263d37971a164743dc33c159dfb4fb4a86f37c5552307
BLAKE2b-256 checksum
How to use checksums
9995d108de3eed0ae29d98c94c918c1245713e7f222dead2d77c24bc4ca7ca0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/44.0.0 requests-toolbelt/0.9.1 tqdm/4.41.1 CPython/3.7.6

Release history Release notifications | RSS feed

3.16.0

2 release files

3.15.1

2 release files

3.14.1

2 release files

3.14.0

2 release files

3.13.0

2 release files

3.12.0

2 release files

3.11.1

2 release files

3.11.0

2 release files

3.9.0

2 release files

3.8.2

2 release files

3.8.1

2 release files

3.8.0

2 release files

3.7.0

2 release files

3.6.1

2 release files

3.6.0

2 release files

3.5.1

2 release files

3.5.0

2 release files

3.4.0

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.1

2 release files

3.1.0

2 release files

3.0.0

2 release files

This release

2.0.0 This release

2 release files

1.12.1

2 release files

1.12.0

2 release files

1.11.2

2 release files

1.11.0

2 release files

1.10.4

2 release files

1.10.3

2 release files

1.10.2

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.3

2 release files

1.6.2

1 release file

1.6.1

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2

2 release files

1.1

2 release files

1.0

2 release files

0.11.0

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.7.0

1 release file

0.6.0

1 release file

0.5.0

1 release file

0.4.3

1 release file

0.4.2

1 release file

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page