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

Supported Python versions version downloads ci coverage

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:

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:

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 also access Mock and MagicMock directly using from mocker fixture:

def test_feature(mocker):
    ret = [mocker.Mock(return_value=True), mocker.Mock(return_value=True)]
    mocker.patch('mylib.func', side_effect=ret)

New in version 0.5

Spy

New in version 0.6

The spy acts exactly like the original method in all cases, except it allows use of mock features with it, like retrieving call count.

From version 0.7 onward it also works for class and static methods. Originally it was only safe to use with instance methods.

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

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

Stub

New in version 0.6

The stub is a mock object that accepts any arguments and is useful to test callbacks, for instance.

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

    stub = mocker.stub()

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

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.3+

  • pytest

  • mock (for Python 2)

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


Download files

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

Source Distribution

pytest-mock-0.8.1.zip (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_mock-0.8.1-py2.py3-none-any.whl (8.7 kB view details)

Uploaded Python 2Python 3

File details

Details for the file pytest-mock-0.8.1.zip.

File metadata

  • Download URL: pytest-mock-0.8.1.zip
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for pytest-mock-0.8.1.zip
Algorithm Hash digest
SHA256 2ba9b5feebc3c4fd5fc34df8c4b8401f9d5936aa8c64be15d74dae303467946b
MD5 d5a05eb51f5466f18eb303b8f48a128a
BLAKE2b-256 09b091a28ca6548e14514596a9b25261b838bd1c190166b54084c3228e24c7fc

See more details on using hashes here.

File details

Details for the file pytest_mock-0.8.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_mock-0.8.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 0c8032b00b80a8c31389c95c519df921e5127d3fee5bbb0c59364ca055ea9c6f
MD5 1c7da808c4cf722710df94cb6a5b3b09
BLAKE2b-256 7002320cbf7b0cea21f3610c08ce25c9232cc67ae4bf6461dda2e878df1e8779

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page