Thin-wrapper around the mock package for easier use with pytest

Overview

pytest-mock

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 pre-commit

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:

It is also possible to use mocking functionality from fixtures of other scopes using the appropriate mock fixture:

  • class_mocker
  • module_mocker
  • package_mocker
  • session_mocker

Type Annotations

New in version 3.3.0.

pytest-mock is fully type annotated, letting users use static type checkers to test their code.

The mocker fixture returns pytest_mock.MockerFixture which can be used to annotate test functions:

from pytest_mock import MockerFixture

def test_foo(mocker: MockerFixture) -> None:
    ...

The type annotations have been checked with mypy, which is the only type checker supported at the moment; other type-checkers might work but are not currently tested.

Spy

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

def test_spy_method(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

def test_spy_function(mocker):
    # mymodule declares `myfunction` which just returns 42
    import mymodule

    spy = mocker.spy(mymodule, "myfunction")
    assert mymodule.myfunction() == 42
    assert spy.call_count == 1
    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 or call_count in the examples 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.

Besides functions and normal methods, mocker.spy also works for class and static methods.

As of version 3.0.0, mocker.spy also works with async def functions.

Note

In versions earlier than 2.0, the attributes were called return_value and side_effect respectively, but due to incompatibilities with unittest.mock they had to be renamed (see #175 for details).

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 pytest's own advanced assertions to return a better diff:

mocker = <pytest_mock.MockerFixture 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, so it will emit a warning when used as such.

If you really intend to mock a context manager, mocker.patch.context_manager exists which won't issue the above warning.

Requirements

  • Python 3.5+
  • pytest

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 py38,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.

Comments
  • Feature: descriptive mock assert wrap

    Feature: descriptive mock assert wrap

    This branch adds original call assertion error message and improves result message. Here is a detailed list of changes:

    • assert both args and kwargs at the same time for a more detailed report
    • update tests to assert the above
    • re-raise original AssertionError implicitly
    • define a DETAILED_ASSERTION template to format the detailed message
    • add mock to py26 dependencies in tox.ini
    • use unittest.mock for py > 3.3
    • small style cleanup (PEP8)

    Attempts to improve on PR #36 according to the points raised in PR #57

    opened by asfaltboy 21
  • Can you make the license on this MIT?

    Can you make the license on this MIT?

    I can't use any form of GPL at work (including LGPL). Even if it was possible, the handling considerations wouldn't be worth it for a plugin. A few months ago I had a remote worker try to borrow code from an LGPL plugin for a project, thinking "hey it's open source, and freedom". Its not easy to convey the ramification of creating a derivative work.

    pytest itself is MIT.

    enhancement help wanted 
    opened by tony 19
  • fixture 'mocker' not found

    fixture 'mocker' not found

    I haven't looked too closely into this bug yet, but the error itself is strange, given that it explicitly lists 'mocker' as one of the available fixtures.

    I had run tox -r previously and everything passed. Then I upgraded

    • pytest (2.9.2) -> 3.0.3
    • pytest-mock (1.2) -> 1.4.0

    And started seeing this failure.

      @pytest.fixture
      def request(mocker):
    E       fixture 'mocker' not found
    >       available fixtures: cache, capfd, capsys, doctest_namespace, mock, mocker, monkeypatch, pytestconfig, record_xml_property, recwarn, request, requests_get, tmpdir, tmpdir_factory
    >       use 'pytest --fixtures [testpath]' for help on them.
    
    

    Code looks something like this:

    import pytest
    from mock import Mock, sentinel
    from requests import codes
    
    @pytest.fixture
    def request(mocker):
        return Mock((), url='https://test-url.com:8000', cookies=None, headers={})
    
    question 
    opened by jaimemarijke 17
  • Python3 + pytest + pytest-mock: Mocks leaking into other test functions breaking assertions?

    Python3 + pytest + pytest-mock: Mocks leaking into other test functions breaking assertions?

    Hi guys! First of all, thank you for everything that you do! It is really appreciated!

    My Question

    Apologies in advance if this issue is blatant, but i've been wrestling with it for several days now. Hopefully someone can shed some new light.

    I'm in the process of converting unit tests for my personal project from unittest -> pytest. Previously I was using the built-in unittest.mock module, but now i'm trying to use the pytest-mock plugin instead.

    I have a sneaking feeling that my tests are leaking mock objects into one another.

    Here's why: NOTE: All Details about my setup (python version, modules etc) listed at bottom of question.

    High-level details:

    # Python version
    Python 3.5.2
    
    # Pytest version ( and plugins )
    pytest==3.0.7
    pytest-benchmark==3.1.0a2
    pytest-catchlog==1.2.2
    pytest-cov==2.4.0
    pytest-ipdb==0.1.dev2
    pytest-leaks==0.2.2
    pytest-mock==1.6.0
    pytest-rerunfailures==2.1.0
    pytest-sugar==0.8.0
    pytest-timeout==1.2.0
    python-dateutil==2.6.0
    python-dbusmock==0.16.7
    

    When I run my tests using the following command:

    py.test --pdb --showlocals -v -R : -k test_subprocess.py

    Everything is fine till we get to test_subprocess_check_command_type. At which point I get the following error:

                # Set mock return types
                # mock_map_type_to_command.return_value = int
        
                # action
                with pytest.raises(TypeError) as excinfo:
                    scarlett_os.subprocess.Subprocess(test_command,
                                                      name=test_name,
                                                      fork=test_fork,
        >                                             run_check_command=True)
        E           Failed: DID NOT RAISE <class 'TypeError'>
        
        excinfo    = <[AttributeError("'ExceptionInfo' object has no attribute 'typename'") raised in repr()] ExceptionInfo object at 0x7f8c380f9dc0>
        mock_fork  = <Mock name='mock_fork' id='140240122195184'>
        mock_logging_debug = <Mock name='mock_logging_debug' id='140240128747640'>
        mock_map_type_to_command = <Mock name='mock_map_type_to_command' id='140240122785112'>
        mocker     = <pytest_mock.MockFixture object at 0x7f8c329f07a8>
        monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f8c329f0810>
        self       = <tests.test_subprocess.TestScarlettSubprocess object at 0x7f8c32aaac20>
        test_command = ['who', '-b']
        test_fork  = False
        test_name  = 'test_who'
        
        tests/test_subprocess.py:267: Failed
        
         tests/test_subprocess.py::TestScarlettSubprocess.test_subprocess_check_command_type ⨯                                                           100% ██████████
    

    BUT!

    If I filter out all of the other tests except for the problematic one then I get:

    via py.test --pdb --showlocals -v -R : -k test_subprocess_check_command_type

        pi@0728af726f1f:~/dev/bossjones-github/scarlett_os$ py.test --pdb --showlocals -v -R : -k test_subprocess_check_command_type
        /usr/local/lib/python3.5/site-packages/_pdbpp_path_hack/pdb.py:4: ResourceWarning: unclosed file <_io.TextIOWrapper name='/usr/local/lib/python3.5/site-packages/pdb.py' mode='r' encoding='UTF-8'>
          os.path.dirname(os.path.dirname(__file__)), 'pdb.py')).read(), os.path.join(
        Test session starts (platform: linux, Python 3.5.2, pytest 3.0.7, pytest-sugar 0.8.0)
        cachedir: .cache
        benchmark: 3.1.0a2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
        rootdir: /home/pi/dev/bossjones-github/scarlett_os, inifile: setup.cfg
        plugins: timeout-1.2.0, sugar-0.8.0, rerunfailures-2.1.0, mock-1.6.0, leaks-0.2.2, ipdb-0.1.dev2, cov-2.4.0, catchlog-1.2.2, benchmark-3.1.0a2
        timeout: 60.0s method: signal
        NOTE: DBUS_SESSION_BUS_ADDRESS environment var not found!
        [DBUS_SESSION_BUS_ADDRESS]: unix:path=/tmp/dbus_proxy_outside_socket
        
         tests/test_subprocess.py::TestScarlettSubprocess.test_subprocess_check_command_type ✓                                                                                                                                                                           100% ██████████
        
        Results (8.39s):
               1 passed
             190 deselected
        pi@0728af726f1f:~/dev/bossjones-github/scarlett_os$
    

    I also tried manually commenting out the following 2 tests and they allowed me to successfully run all the tests again:

    • test_subprocess_init
    • test_subprocess_map_type_to_command

    Can anyone see anything blatently wrong with my setup? I've read several blog posts on "where to mock", and looked at the docs themselves several times, not sure what i'm missing. https://docs.python.org/3/library/unittest.mock.html

    My Setup Details

    Here is everything that might be required to solve this. Let me know if I need to provide any more information!

    Also ... please excuse how messy my code looks and all of the comment blocks. I'm a big note taker when i'm learning something new ... I'll make everything more pythonic and cleaner in the near future :)

    My code:

        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
    
        """Scarlett Dbus Service. Implemented via MPRIS D-Bus Interface Specification."""
    
        from __future__ import with_statement, division, absolute_import
    
        import os
        import sys
        from scarlett_os.exceptions import SubProcessError
        from scarlett_os.exceptions import TimeOutError
        import logging
        from scarlett_os.internal.gi import GObject
        from scarlett_os.internal.gi import GLib
    
        logger = logging.getLogger(__name__)
    
    
        def check_pid(pid):
            """Check For the existence of a unix pid."""
            try:
                os.kill(pid, 0)
            except OSError:
                return False
            else:
                return True
    
    
        class Subprocess(GObject.GObject):
            """
            GObject API for handling child processes.
    
            :param command: The command to be run as a subprocess.
            :param fork: If `True` this process will be detached from its parent and
                         run independent. This means that no excited-signal will be emited.
    
            :type command: `list`
            :type fork: `bool`
            """
    
            __gtype_name__ = 'Subprocess'
            __gsignals__ = {
                'exited': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_INT, GObject.TYPE_INT))
            }
    
            def __init__(self, command, name=None, fork=False, run_check_command=True):
                """Create instance of Subprocess."""
    
                GObject.GObject.__init__(self)
    
                self.process = None
                self.pid = None
    
                if not fork:
                    self.stdout = True
                    self.stderr = True
                else:
                    self.stdout = False
                    self.stderr = False
    
                self.forked = fork
    
                # Verify that command is properly formatted 
                # and each argument is of type str
                if run_check_command:
                    self.check_command_type(command)
    
                self.command = command
                self.name = name
    
                logger.debug("command: {}".format(self.command))
                logger.debug("name: {}".format(self.name))
                logger.debug("forked: {}".format(self.forked))
                logger.debug("process: {}".format(self.process))
                logger.debug("pid: {}".format(self.pid))
    
                if fork:
                    self.fork()
    
            # TODO: Add these arguments so we can toggle stdout
            # def spawn_command(self, standard_input=False, standard_output=False, standard_error=False):
            def spawn_command(self):
                # DO_NOT_REAP_CHILD
                # Don't reap process automatically so it is possible to detect when it is closed.
                return GLib.spawn_async(self.command,
                                        flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD
                                        )
    
            def map_type_to_command(self, command):
                """Return: Map after applying type to several objects in an array"""
                # NOTE: In python3, many processes that iterate over iterables return iterators themselves. 
                # In most cases, this ends up saving memory, and should make things go faster.
                # cause of that, we need to call list() over the map object
                return list(map(type, command))
    
            def check_command_type(self, command):
    
                types = self.map_type_to_command(command)
    
                if type(types) is not list:
                    raise TypeError("Variable types should return a list in python3. Got: {}".format(types))
    
                # NOTE: str is a built-in function (actually a class) which converts its argument to a string. 
                # string is a module which provides common string operations.
                # source: http://stackoverflow.com/questions/2026038/relationship-between-string-module-and-str
                for t in types:
                    if t is not str:
                        raise TypeError("Executables and arguments must be str objects. types: {}".format(t))
    
                logger.debug("Running Command: %r" % " ".join(command))
                return True
    
            def run(self):
                """Run the process."""
    
                # NOTE: DO_NOT_REAP_CHILD: the child will not be automatically reaped;
                # you must use g_child_watch_add yourself (or call waitpid or handle `SIGCHLD` yourself),
                # or the child will become a zombie.
                # source:
                # http://valadoc.org/#!api=glib-2.0/GLib.SpawnFlags.DO_NOT_REAP_CHILD
    
                # NOTE: SEARCH_PATH: argv[0] need not be an absolute path, it will be looked for in the user's PATH
                # source:
                # http://lazka.github.io/pgi-docs/#GLib-2.0/flags.html#GLib.SpawnFlags.SEARCH_PATH
    
                self.pid, self.stdin, self.stdout, self.stderr = self.spawn_command()
    
                logger.debug("command: {}".format(self.command))
                logger.debug("stdin: {}".format(self.stdin))
                logger.debug("stdout: {}".format(self.stdout))
                logger.debug("stderr: {}".format(self.stderr))
                logger.debug("pid: {}".format(self.pid))
    
                # close file descriptor
                self.pid.close()
    
                print(self.stderr)
    
                # NOTE: GLib.PRIORITY_HIGH = -100
                # Use this for high priority event sources.
                # It is not used within GLib or GTK+.
                watch = GLib.child_watch_add(GLib.PRIORITY_HIGH, 
                                             self.pid, 
                                             self.exited_cb)
    
                return self.pid
    
            def exited_cb(self, pid, condition):
                if not self.forked:
                    self.emit('exited', pid, condition)
    
            def fork(self):
                """Fork the process."""
                try:
                    # first fork
                    pid = os.fork()
                    if pid > 0:
                        logger.debug('pid greater than 0 first time')
                        sys.exit(0)
                except OSError as e:
                    logger.error('Error forking process first time')
                    sys.exit(1)
    
                # Change the current working directory to path.
                os.chdir("/")
    
                # Description: setsid() creates a new session if the calling process is not a process group leader. 
                # The calling process is the leader of the new session, 
                # the process group leader of the new process group, 
                # and has no controlling terminal. 
                # The process group ID and session ID of the calling process are set to the PID of the calling process. 
                # The calling process will be the only process in this new process group and in this new session.
    
                # Return Value: On success, the (new) session ID of the calling process is returned. 
                # On error, (pid_t) -1 is returned, and errno is set to indicate the error.
                os.setsid()
    
                # Set the current numeric umask and return the previous umask.
                os.umask(0)
    
                try:
                    # second fork
                    pid = os.fork()
                    if pid > 0:
                        logger.debug('pid greater than 0 second time')
                        sys.exit(0)
                except OSError as e:
                    logger.error('Error forking process second time')
                    sys.exit(1)
    

    My Test:

        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
    
        """
        test_subprocess
        ----------------------------------
        """
    
        import os
        import sys
        import pytest
    
        import scarlett_os
        # import signal
        # import builtins
        # import re
    
        class TestScarlettSubprocess(object):
            '''Units tests for Scarlett Subprocess, subclass of GObject.Gobject.'''
    
            def test_check_pid_os_error(self, mocker):
                # Feels like mocks are leaking into other tests, 
                # stop mock before starting each test function
                mocker.stopall()
    
                # Setup mock objects
                kill_mock = mocker.MagicMock(name=__name__ + "_kill_mock_OSError")
                kill_mock.side_effect = OSError
    
                # patch things
                mocker.patch.object(scarlett_os.subprocess.os, 'kill', kill_mock)
    
                # When OSError occurs, throw False
                assert not scarlett_os.subprocess.check_pid(4353634632623)
                # Verify that os.kill only called once
                assert kill_mock.call_count == 1
    
            def test_check_pid(self, mocker):
                # Feels like mocks are leaking into other tests, 
                # stop mock before starting each test function
                mocker.stopall()
    
                # Setup mock objects
                kill_mock = mocker.MagicMock(name=__name__ + "_kill_mock")
    
                mocker.patch.object(scarlett_os.subprocess.os, 'kill', kill_mock)
    
                result = scarlett_os.subprocess.check_pid(123)
                assert kill_mock.called
                # NOTE: test against signal 0
                # sending the signal 0 to a given PID just checks if any
                # process with the given PID is running and you have the
                # permission to send a signal to it.
                kill_mock.assert_called_once_with(123, 0)
                assert result is True
    
            # FIXME: I THINK THIS GUYS IS LEAKING MOCK OBJECTS
            def test_subprocess_init(self, mocker):
                # Feels like mocks are leaking into other tests, 
                # stop mock before starting each test function
                mocker.stopall()
    
                mock_check_command_type = MagicMock(name="mock_check_command_type")
                mock_check_command_type.return_value = True
                mock_fork = mocker.MagicMock(name="mock_fork")
                mock_logging_debug = mocker.MagicMock(name="mock_logging_debug")
    
                # mock
                mocker.patch.object(scarlett_os.subprocess.logging.Logger, 'debug', mock_logging_debug)
                mocker.patch.object(scarlett_os.subprocess.Subprocess, 'check_command_type', mock_check_command_type)
                mocker.patch.object(scarlett_os.subprocess.Subprocess, 'fork', mock_fork)
    
                # NOTE: On purpose this is an invalid cmd. Should be of type array
                test_command = ['who']
    
                test_name = 'test_who'
                test_fork = False
    
                s_test = scarlett_os.subprocess.Subprocess(test_command,
                                                           name=test_name,
                                                           fork=test_fork)
    
                # action
                assert s_test.check_command_type(test_command) is True
                mock_check_command_type.assert_called_with(['who'])
                assert not s_test.process
                assert not s_test.pid
                assert s_test.name == 'test_who'
                assert not s_test.forked
                assert s_test.stdout is True
                assert s_test.stderr is True
    
                mock_logging_debug.assert_any_call("command: ['who']")
                mock_logging_debug.assert_any_call("name: test_who")
                mock_logging_debug.assert_any_call("forked: False")
                mock_logging_debug.assert_any_call("process: None")
                mock_logging_debug.assert_any_call("pid: None")
                mock_fork.assert_not_called()
    
            # FIXME: I THINK THIS GUYS IS LEAKING MOCK OBJECTS
            def test_subprocess_map_type_to_command(self, mocker):
                """Using the mock.patch decorator (removes the need to import builtins)"""
                # Feels like mocks are leaking into other tests, 
                # stop mock before starting each test function
                mocker.stopall()
    
                mock_check_command_type = mocker.MagicMock(name="mock_check_command_type")
                mock_check_command_type.return_value = True
                mock_fork = mocker.MagicMock(name="mock_fork")
                mock_logging_debug = mocker.MagicMock(name="mock_logging_debug")
    
                # mock
                mocker.patch.object(scarlett_os.subprocess.logging.Logger, 'debug', mock_logging_debug)
                mocker.patch.object(scarlett_os.subprocess.Subprocess, 'check_command_type', mock_check_command_type)
                mocker.patch.object(scarlett_os.subprocess.Subprocess, 'fork', mock_fork)
    
                # NOTE: On purpose this is an invalid cmd. Should be of type array
                test_command = ["who", "-b"]
                test_name = 'test_who'
                test_fork = False
    
                # create subprocess object
                s_test = scarlett_os.subprocess.Subprocess(test_command,
                                                           name=test_name,
                                                           fork=test_fork)
                mocker.spy(s_test, 'map_type_to_command')
                assert isinstance(s_test.map_type_to_command(test_command), list)
                assert s_test.map_type_to_command.call_count == 1
    
                assert s_test.check_command_type(test_command)
                assert s_test.check_command_type(
                    test_command) == mock_check_command_type.return_value
    
            def test_subprocess_check_command_type(self, mocker):
                """Using the mock.patch decorator (removes the need to import builtins)"""
                # Feels like mocks are leaking into other tests, 
                # stop mock before starting each test function
                mocker.stopall()
    
                test_command = ["who", "-b"]
                test_name = 'test_who'
                test_fork = False
    
                # mock
                mock_map_type_to_command = mocker.MagicMock(name="mock_map_type_to_command")
                # mock_map_type_to_command.return_value = int
                mock_map_type_to_command.side_effect = [int, [int, int]]
                mock_fork = mocker.MagicMock(name="mock_fork")
                mock_logging_debug = mocker.MagicMock(name="mock_logging_debug")
    
                mocker.patch.object(scarlett_os.subprocess.logging.Logger, 'debug', mock_logging_debug)
                mocker.patch.object(scarlett_os.subprocess.Subprocess, 'map_type_to_command', mock_map_type_to_command)
                mocker.patch.object(scarlett_os.subprocess.Subprocess, 'fork', mock_fork)
    
    
                # action
                with pytest.raises(TypeError) as excinfo:
                    scarlett_os.subprocess.Subprocess(test_command,
                                                      name=test_name,
                                                      fork=test_fork,
                                                      run_check_command=True)
                assert str(
                    excinfo.value) == "Variable types should return a list in python3. Got: <class 'int'>"
    
                with pytest.raises(TypeError) as excinfo:
                    scarlett_os.subprocess.Subprocess(test_command,
                                                      name=test_name,
                                                      fork=test_fork,
                                                      run_check_command=True)
    
                assert str(
                    excinfo.value) == "Executables and arguments must be str objects. types: <class 'int'>"
    

    My folder structure( Note I removed a couple things since it was overly verbose ):

        pi@0728af726f1f:~/dev/bossjones-github/scarlett_os$ tree -I *.pyc
        .
        ├── requirements_dev.txt
        ├── requirements_test_experimental.txt
        ├── requirements_test.txt
        ├── requirements.txt
        ├── scarlett_os
        │   ├── automations
        │   │   ├── __init__.py
        │   │   └── __pycache__
        │   ├── commands.py
        │   ├── compat.py
        │   ├── config.py
        │   ├── const.py
        │   ├── core.py
        │   ├── emitter.py
        │   ├── exceptions.py
        │   ├── __init__.py
        │   ├── internal
        │   │   ├── debugger.py
        │   │   ├── deps.py
        │   │   ├── encoding.py
        │   │   ├── formatting.py
        │   │   ├── gi.py
        │   │   ├── __init__.py
        │   │   ├── path.py
        │   │   ├── __pycache__
        │   │   └── system_utils.py
        │   ├── listener.py
        │   ├── loader.py
        │   ├── logger.py
        │   ├── log.py
        │   ├── __main__.py
        │   ├── mpris.py
        │   ├── player.py
        │   ├── __pycache__
        │   ├── receiver.py
        │   ├── speaker.py
        │   ├── subprocess.py
        │   ├── tasker.py
        │   ├── tools
        │   │   ├── __init__.py
        │   │   ├── package.py
        │   │   ├── __pycache__
        │   │   └── verify.py
        │   └── utility
        │       ├── audio.py
        │       ├── dbus_runner.py
        │       ├── dbus_utils.py
        │       ├── distance.py
        │       ├── dt.py
        │       ├── file.py
        │       ├── generators.py
        │       ├── gnome.py
        │       ├── __init__.py
        │       ├── location.py
        │       ├── __pycache__
        │       ├── temperature.py
        │       ├── threadmanager.py
        │       ├── thread.py
        │       ├── unit_system.py
        │       └── yaml.py
        ├── setup.cfg
        ├── setup.py
        ├── tests
        │   ├── common_integration.py
        │   ├── common.py
        │   ├── helpers
        │   │   ├── __init__.py
        │   │   ├── __pycache__
        │   │   ├── test_config_validation.py
        │   │   ├── test_entity.py
        │   │   └── test_init.py
        │   ├── __init__.py
        │   ├── integration
        │   │   ├── baseclass.py
        │   │   ├── conftest.py
        │   │   ├── __init__.py
        │   │   ├── __pycache__
        │   │   ├── README.md
        │   │   ├── stubs.py
        │   │   ├── test_integration_end_to_end.py
        │   │   ├── test_integration_listener.py
        │   │   ├── test_integration_mpris.py
        │   │   ├── test_integration_player.py
        │   │   ├── test_integration_tasker.py
        │   │   ├── test_integration_tasker.py.enable_sound.diff
        │   │   └── test_integration_threadmanager.py
        │   ├── internal
        │   │   ├── __init__.py
        │   │   ├── __pycache__
        │   │   ├── test_deps.py
        │   │   ├── test_encoding.py
        │   │   └── test_path.py
        │   ├── performancetests
        │   │   ├── baseclass.py
        │   │   ├── __init__.py
        │   │   └── __pycache__
        │   ├── __pycache__
        │   ├── run_all_tests
        │   ├── run_dbus_tests.sh
        │   ├── test_cli.py
        │   ├── test_commands.py
        │   ├── testing_config
        │   │   └── custom_automations
        │   │       ├── light
        │   │       │   └── test.py
        │   │       └── switch
        │   │           └── test.py
        │   ├── test_listener.py
        │   ├── test_mpris.py
        │   ├── test_player.py
        │   ├── test_scarlett_os.py
        │   ├── test_speaker.py
        │   ├── test_subprocess.py
        │   ├── test_tasker.py
        │   ├── test_threadmanager.py
        │   ├── tools_common.py
        │   ├── unit_scarlett_os.py
        │   └── utility
        │       ├── __init__.py
        │       ├── __pycache__
        │       ├── test_dbus_utils.py
        │       ├── test_distance.py
        │       ├── test_dt.py
        │       ├── test_gnome.py
        │       ├── test_init.py
        │       ├── test_location.py
        │       ├── test_unit_system.py
        │       └── test_yaml.py
        67 directories, 256 files
        pi@0728af726f1f:~/dev/bossjones-github/scarlett_os$
    

    Other details( Extended pip freeze just in case of incompatibilities ):

        # Python version
        Python 3.5.2
    
        # Pytest version ( and plugins )
        pytest==3.0.7
        pytest-benchmark==3.1.0a2
        pytest-catchlog==1.2.2
        pytest-cov==2.4.0
        pytest-ipdb==0.1.dev2
        pytest-leaks==0.2.2
        pytest-mock==1.6.0
        pytest-rerunfailures==2.1.0
        pytest-sugar==0.8.0
        pytest-timeout==1.2.0
        python-dateutil==2.6.0
        python-dbusmock==0.16.7
    
    
        # Pip Freeze ( Just in case )
        alabaster==0.7.10
        appdirs==1.4.3
        argh==0.26.2
        asn1crypto==0.22.0
        astroid==1.5.2
        Babel==2.4.0
        bleach==2.0.0
        bumpversion==0.5.3
        cffi==1.10.0
        click==6.7
        click-plugins==1.0.3
        colorama==0.3.7
        colorlog==2.10.0
        coverage==4.3.4
        coveralls==1.1
        cryptography==1.8.1
        Cython==0.25.2
        decorator==4.0.11
        docopt==0.6.2
        docutils==0.13.1
        ecdsa==0.13
        entrypoints==0.2.2
        Fabric3==1.12.post1
        fancycompleter==0.7
        fields==5.0.0
        flake8==3.3.0
        flake8-docstrings==1.0.3
        flake8-polyfill==1.0.1
        freezegun==0.3.8
        gnureadline==6.3.3
        graphviz==0.6
        html5lib==0.999999999
        hunter==1.4.1
        idna==2.5
        imagesize==0.7.1
        ipdb==0.10.2
        ipykernel==4.6.1
        ipython==6.0.0
        ipython-genutils==0.2.0
        ipywidgets==6.0.0
        isort==4.2.5
        jedi==0.10.2
        Jinja2==2.9.6
        jsonschema==2.6.0
        jupyter==1.0.0
        jupyter-client==5.0.1
        jupyter-console==5.1.0
        jupyter-core==4.3.0
        lazy-object-proxy==1.2.2
        MarkupSafe==1.0
        mccabe==0.6.1
        mistune==0.7.4
        mock==2.0.0
        mock-open==1.3.1
        mypy-lang==0.4.6
        nbconvert==5.1.1
        nbformat==4.3.0
        notebook==5.0.0
        objgraph==3.1.0
        ordereddict==1.1
        packaging==16.8
        pandocfilters==1.4.1
        paramiko==1.18.2
        pathtools==0.1.2
        pbr==1.10.0
        pdbpp==0.8.3
        pexpect==4.2.1
        pickleshare==0.7.4
        pluggy==0.4.0
        plumbum==1.6.3
        prompt-toolkit==1.0.14
        psutil==5.2.2
        ptyprocess==0.5.1
        py==1.4.33
        py-cpuinfo==3.2.0
        pyasn1==0.2.3
        pycodestyle==2.3.1
        pycparser==2.17
        pycrypto==2.6.1
        pydbus==0.6.0
        pydocstyle==2.0.0
        pyflakes==1.5.0
        pygal==2.3.1
        pygaljs==1.0.1
        Pygments==2.2.0
        pygobject==3.22.0
        pylint==1.7.1
        pyparsing==2.2.0
        pystuck==0.8.5
        pytest==3.0.7
        pytest-benchmark==3.1.0a2
        pytest-catchlog==1.2.2
        pytest-cov==2.4.0
        pytest-ipdb==0.1.dev2
        pytest-leaks==0.2.2
        pytest-mock==1.6.0
        pytest-rerunfailures==2.1.0
        pytest-sugar==0.8.0
        pytest-timeout==1.2.0
        python-dateutil==2.6.0
        python-dbusmock==0.16.7
        pytz==2017.2
        PyYAML==3.12
        pyzmq==16.0.2
        qtconsole==4.3.0
        requests==2.13.0
        requests-mock==1.3.0
        rpyc==3.3.0
        -e [email protected]:bossjones/scarlett_os.git@c14ffcde608da12f5c2d4d9b81a63c7e618b3eed#egg=scarlett_os
        simplegeneric==0.8.1
        six==1.10.0
        snowballstemmer==1.2.1
        Sphinx==1.5.5
        stevedore==1.18.0
        termcolor==1.1.0
        terminado==0.6
        testpath==0.3
        tornado==4.5.1
        tox==2.7.0
        traitlets==4.3.2
        typing==3.6.1
        virtualenv==15.0.3
        virtualenv-clone==0.2.6
        virtualenvwrapper==4.7.2
        voluptuous==0.9.3
        watchdog==0.8.3
        wcwidth==0.1.7
        webencodings==0.5.1
        widgetsnbextension==2.0.0
        wmctrl==0.3
        wrapt==1.10.10
        xdot==0.7
    
    opened by bossjones 15
  • Allow patching methods by reference

    Allow patching methods by reference

    In our codebase's unit tests we often mock out dependencies by patching individual methods of instances, i.e.

    def test_something(mocker: MockerFixture):
       mocker.patch.object(foo_client, 'get_bar', return_value=42)
       ...
    

    Other times we patch them on the class level, which has the advantage of not needing access to a particular instance:

    def test_something(mocker: MockerFixture):
       mocker.patch.object(FooClient, 'get_bar', return_value=42)
       ...
    

    It always rubbed me the wrong way how the 2nd argument to this patch.object is "stringly typed". This prevents our IDE from being aware of the mocking when refactoring, and precludes the conveniences of symbolic code navigation ("go to definition", "find references").

    Here's an experimental addition I've made in our code base: https://gist.github.com/ikonst/cc28e815008c6487af91a10e3a1fdd7a

    For bounded methods, converting a method reference to (instance, name) is very easy. For unbounded methods, a rather hacky approach is required, but I believe it's reasonable for test code and the benefits outweigh the hackiness :)

    enhancement 
    opened by ikonst 14
  • xxx() missing 1 required positional argument: 'mocker'

    xxx() missing 1 required positional argument: 'mocker'

    I'm using pytest 5.3.0 with pytest-mock 1.12.1, and in a pytest class I want to temporarily mock a function of an object returned by some other module function. When I use test_calls_operation(mocker) outside a test class, then the mocker arg gets filled in by pytest-mock as expected. However, when I declare the test as shown below, I get test_calls_operation() missing 1 required positional argument: 'mocker'. What am I doing wrong? I sifted through the documentation and especially StackOverflow, but I seem to miss the knack of getting the mocker arg` automatically set as needed.

    class KeysModuleTests(TestCase):
        def test_calls_operation(self, mocker):
            keys = mnt.keys.end()
            mocker.spy(keys, 'op_end')
            # ...
    
    opened by thediveo 14
  • Test failures in test_assert_called_args_with_introspection

    Test failures in test_assert_called_args_with_introspection

    Whilst attempting to integrate pytest-mock to the Debian CI infrastructure, I encountered the following issue when running the tests against the installed version from the Debian package:

    =================================== FAILURES ===================================
    __________________ test_assert_called_args_with_introspection __________________
    
    mocker = <pytest_mock.MockFixture object at 0x7f46460fce10>
    
        def test_assert_called_args_with_introspection(mocker):
            stub = mocker.stub()
        
            complex_args = ('a', 1, set(['test']))
            wrong_args = ('b', 2, set(['jest']))
        
            stub(*complex_args)
            stub.assert_called_with(*complex_args)
            stub.assert_called_once_with(*complex_args)
        
            with assert_argument_introspection(complex_args, wrong_args):
                stub.assert_called_with(*wrong_args)
    >           stub.assert_called_once_with(*wrong_args)
    
    test_pytest_mock.py:390: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    /usr/lib/python2.7/contextlib.py:35: in __exit__
        self.gen.throw(type, value, traceback)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    left = ('a', 1, set(['test'])), right = ('b', 2, set(['jest']))
    
        @contextmanager
        def assert_argument_introspection(left, right):
            """
            Assert detailed argument introspection is used
            """
            try:
                yield
            except AssertionError as e:
                # this may be a bit too assuming, but seems nicer then hard-coding
                import _pytest.assertion.util as util
                # NOTE: we assert with either verbose or not, depending on how our own
                #       test was run by examining sys.argv
                verbose = any(a.startswith('-v') for a in sys.argv)
                expected = '\n  '.join(util._compare_eq_iterable(left, right, verbose))
    >           assert expected in str(e)
    E           assert "Full diff:\n  - ('a', 1, set(['test']))\n  ?   ^   ^        ^\n  + ('b', 2, set(['jest']))\n  ?   ^   ^        ^" in "Expected call: mock('b', 2, set(['jest']))\nActual call: mock('a', 1, set(['test']))\n\npytest introspection follows:\n\nArgs:\n"
    E            +  where "Expected call: mock('b', 2, set(['jest']))\nActual call: mock('a', 1, set(['test']))\n\npytest introspection follows:\n\nArgs:\n" = str(AssertionError(u"Expected call: mock('b', 2, set(['jest']))\nActual call: mock('a', 1, set(['test']))\n\npytest introspection follows:\n\nArgs:\n",))
    
    test_pytest_mock.py:346: AssertionError
    _________________ test_assert_called_kwargs_with_introspection _________________
    
    mocker = <pytest_mock.MockFixture object at 0x7f464627c150>
    
        def test_assert_called_kwargs_with_introspection(mocker):
            stub = mocker.stub()
        
            complex_kwargs = dict(foo={'bar': 1, 'baz': 'spam'})
            wrong_kwargs = dict(foo={'goo': 1, 'baz': 'bran'})
        
            stub(**complex_kwargs)
            stub.assert_called_with(**complex_kwargs)
            stub.assert_called_once_with(**complex_kwargs)
        
            with assert_argument_introspection(complex_kwargs, wrong_kwargs):
                stub.assert_called_with(**wrong_kwargs)
    >           stub.assert_called_once_with(**wrong_kwargs)
    
    test_pytest_mock.py:405: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    /usr/lib/python2.7/contextlib.py:35: in __exit__
        self.gen.throw(type, value, traceback)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    left = {'foo': {'bar': 1, 'baz': 'spam'}}
    right = {'foo': {'baz': 'bran', 'goo': 1}}
    
        @contextmanager
        def assert_argument_introspection(left, right):
            """
            Assert detailed argument introspection is used
            """
            try:
                yield
            except AssertionError as e:
                # this may be a bit too assuming, but seems nicer then hard-coding
                import _pytest.assertion.util as util
                # NOTE: we assert with either verbose or not, depending on how our own
                #       test was run by examining sys.argv
                verbose = any(a.startswith('-v') for a in sys.argv)
                expected = '\n  '.join(util._compare_eq_iterable(left, right, verbose))
    >           assert expected in str(e)
    E           assert "Full diff:\n  - {'foo': {'bar': 1, 'baz': 'spam'}}\n  + {'foo': {'baz': 'bran', 'goo': 1}}" in "Expected call: mock(foo={'goo': 1, 'baz': 'bran'})\nActual call: mock(foo={'baz': 'spam', 'bar': 1})\n\npytest introspection follows:\n\nKwargs:\n"
    E            +  where "Expected call: mock(foo={'goo': 1, 'baz': 'bran'})\nActual call: mock(foo={'baz': 'spam', 'bar': 1})\n\npytest introspection follows:\n\nKwargs:\n" = str(AssertionError(u"Expected call: mock(foo={'goo': 1, 'baz': 'bran'})\nActual ca...foo={'baz': 'spam', 'bar': 1})\n\npytest introspection follows:\n\nKwargs:\n",))
    
    test_pytest_mock.py:346: AssertionError
    _________________________ test_detailed_introspection __________________________
    
    testdir = <Testdir local('/tmp/pytest-of-root/pytest-0/testdir/test_detailed_introspection0')>
    
        def test_detailed_introspection(testdir):
            """Check that the "mock_use_standalone" is being used.
            """
            testdir.makepyfile("""
                def test(mocker):
                    m = mocker.Mock()
                    m('fo')
                    m.assert_called_once_with('', bar=4)
            """)
            result = testdir.runpytest('-s')
            result.stdout.fnmatch_lines([
                "*AssertionError: Expected call: mock('', bar=4)*",
                "*Actual call: mock('fo')*",
                "*pytest introspection follows:*",
                '*Args:',
                "*assert ('fo',) == ('',)",
                "*At index 0 diff: 'fo' != ''*",
                "*Use -v to get the full diff*",
                "*Kwargs:*",
                "*assert {} == {'bar': 4}*",
                "*Right contains more items:*",
                "*{'bar': 4}*",
    >           "*Use -v to get the full diff*",
            ])
    E       Failed: nomatch: "*AssertionError: Expected call: mock('', bar=4)*"
    E           and: u'============================= test session starts =============================='
    E           and: u'platform linux2 -- Python 2.7.14+, pytest-3.2.5, py-1.4.34, pluggy-0.4.0'
    E           and: u'rootdir: /tmp/pytest-of-root/pytest-0/testdir/test_detailed_introspection0, inifile:'
    E           and: u'plugins: mock-1.6.3'
    E           and: u'collected 1 item'
    E           and: u''
    E           and: u'test_detailed_introspection.py F'
    E           and: u''
    E           and: u'=================================== FAILURES ==================================='
    E           and: u'_____________________________________ test _____________________________________'
    E           and: u''
    E           and: u'mocker = <pytest_mock.MockFixture object at 0x7f4646277c90>'
    E           and: u''
    E           and: u'    def test(mocker):'
    E           and: u'        m = mocker.Mock()'
    E           and: u"        m('fo')"
    E           and: u">       m.assert_called_once_with('', bar=4)"
    E       fnmatch: "*AssertionError: Expected call: mock('', bar=4)*"
    E          with: u"E       AssertionError: Expected call: mock('', bar=4)"
    E       fnmatch: "*Actual call: mock('fo')*"
    E          with: u"E       Actual call: mock('fo')"
    E       nomatch: '*pytest introspection follows:*'
    E           and: u'E       '
    E       fnmatch: '*pytest introspection follows:*'
    E          with: u'E       pytest introspection follows:'
    E       nomatch: '*Args:'
    E           and: u'E       '
    E       fnmatch: '*Args:'
    E          with: u'E       Args:'
    E       nomatch: "*assert ('fo',) == ('',)"
    E           and: u'E       '
    E           and: u'E       Kwargs:'
    E           and: u''
    E           and: u'test_detailed_introspection.py:4: AssertionError'
    E           and: u'=========================== 1 failed in 0.01 seconds ==========================='
    E           and: u''
    E       remains unmatched: "*assert ('fo',) == ('',)"
    
    /tmp/autopkgtest.31sHEi/autopkgtest_tmp/test_pytest_mock.py:535: Failed
    ----------------------------- Captured stdout call -----------------------------
    ============================= test session starts ==============================
    platform linux2 -- Python 2.7.14+, pytest-3.2.5, py-1.4.34, pluggy-0.4.0
    rootdir: /tmp/pytest-of-root/pytest-0/testdir/test_detailed_introspection0, inifile:
    plugins: mock-1.6.3
    collected 1 item
    
    test_detailed_introspection.py F
    
    =================================== FAILURES ===================================
    _____________________________________ test _____________________________________
    
    mocker = <pytest_mock.MockFixture object at 0x7f4646277c90>
    
        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       
    E       Kwargs:
    
    test_detailed_introspection.py:4: AssertionError
    =========================== 1 failed in 0.01 seconds ===========================
    ========== 3 failed, 38 passed, 1 skipped, 2 xfailed in 0.69 seconds ===========
    
    

    The plugin seems to be correctly registered:

    ============================= test session starts ==============================
    platform linux2 -- Python 2.7.14+, pytest-3.2.5, py-1.4.34, pluggy-0.4.0 -- /usr/bin/python2.7
    cachedir: .cache
    rootdir: /tmp/autopkgtest.31sHEi/autopkgtest_tmp, inifile:
    plugins: mock-1.6.3
    collecting ... collected 44 items
    

    The same thing happens for both Python 2 and Python 3.

    opened by ghisvail 13
  • Guidance on

    Guidance on "un-spying" a method

    Hi, I couldn't quite figure out how to un-spy a spied method yet. I'm not sure if it's even possible after browsing through the source code.

    spy_foo = mocker.spy(module, "foo")
    
    # do something
    
    # how to un-spy `spy_foo`?
    

    Any ideas or suggestions on how to achieve it? 🙏

    opened by melvinkcx 12
  • 3.6.0: pytest is failing

    3.6.0: pytest is failing

    + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
    + /usr/bin/python3 -Bm pytest -ra
    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.8.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
    rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-mock-3.6.0, configfile: tox.ini
    plugins: mock-3.6.0, forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, asyncio-0.14.0, expect-1.1.0, cov-2.11.1, httpbin-1.0.0, xdist-2.2.1, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, pyfakefs-4.4.0, freezegun-0.4.2, cases-3.4.6, hypothesis-6.10.1, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, flaky-3.7.0
    collected 72 items
    
    tests/test_pytest_mock.py ................................................FF.......FFF............                                                                   [100%]
    
    ================================================================================= FAILURES =================================================================================
    ________________________________________________________________ test_assert_called_args_with_introspection ________________________________________________________________
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>, args = (<MagicMock spec='function' id='140136265299184'>, 'b', 2, {'jest'})
    kwargs = {}, __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock('b', 2, {'jest'})\nActual: mock('a', 1, {'test'})\n\npytest introspection follows:\n\nArgs:\n"
    __mock_self = <MagicMock spec='function' id='140136265299184'>, actual_args = ('a', 1, {'test'}), actual_kwargs = {}, introspection = '\nArgs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
    >           __wrapped_mock_method__(*args, **kwargs)
    
    ../../BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <MagicMock spec='function' id='140136265299184'>, args = ('b', 2, {'jest'}), kwargs = {}, expected = ('', <BoundArguments (args=('b', 2, {'jest'}))>)
    actual = ('', <BoundArguments (args=('a', 1, {'test'}))>), _error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f7404609a60>
    cause = None
    
        def assert_called_with(self, /, *args, **kwargs):
            """assert that the last call was made with the specified arguments.
    
            Raises an AssertionError if the args and keyword args passed in are
            different to the last call to the mock."""
            if self.call_args is None:
                expected = self._format_mock_call_signature(args, kwargs)
                actual = 'not called.'
                error_message = ('expected call not found.\nExpected: %s\nActual: %s'
                        % (expected, actual))
                raise AssertionError(error_message)
    
            def _error_message():
                msg = self._format_mock_failure_message(args, kwargs)
                return msg
            expected = self._call_matcher((args, kwargs))
            actual = self._call_matcher(self.call_args)
            if expected != actual:
                cause = expected if isinstance(expected, Exception) else None
    >           raise AssertionError(_error_message()) from cause
    E           AssertionError: expected call not found.
    E           Expected: mock('b', 2, {'jest'})
    E           Actual: mock('a', 1, {'test'})
    
    /usr/lib64/python3.8/unittest/mock.py:913: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    left = ('a', 1, {'test'}), right = ('b', 2, {'jest'})
    
        @contextmanager
        def assert_argument_introspection(left: Any, right: Any) -> Generator[None, None, None]:
            """
            Assert detailed argument introspection is used
            """
            try:
    >           yield
    
    tests/test_pytest_mock.py:509:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    mocker = <pytest_mock.plugin.MockerFixture object at 0x7f7404503550>
    
        @pytest.mark.usefixtures("needs_assert_rewrite")
        def test_assert_called_args_with_introspection(mocker: MockerFixture) -> None:
            stub = mocker.stub()
    
            complex_args = ("a", 1, {"test"})
            wrong_args = ("b", 2, {"jest"})
    
            stub(*complex_args)
            stub.assert_called_with(*complex_args)
            stub.assert_called_once_with(*complex_args)
    
            with assert_argument_introspection(complex_args, wrong_args):
    >           stub.assert_called_with(*wrong_args)
    
    tests/test_pytest_mock.py:583:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    args = (<MagicMock spec='function' id='140136265299184'>, 'b', 2, {'jest'}), kwargs = {}, __tracebackhide__ = True
    
        def wrap_assert_called_with(*args: Any, **kwargs: Any) -> None:
            __tracebackhide__ = True
    >       assert_wrapper(_mock_module_originals["assert_called_with"], *args, **kwargs)
    
    ../../BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:436:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>, args = (<MagicMock spec='function' id='140136265299184'>, 'b', 2, {'jest'})
    kwargs = {}, __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock('b', 2, {'jest'})\nActual: mock('a', 1, {'test'})\n\npytest introspection follows:\n\nArgs:\n"
    __mock_self = <MagicMock spec='function' id='140136265299184'>, actual_args = ('a', 1, {'test'}), actual_kwargs = {}, introspection = '\nArgs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
                __wrapped_mock_method__(*args, **kwargs)
                return
            except AssertionError as e:
                if getattr(e, "_mock_introspection_applied", 0):
                    msg = str(e)
                else:
                    __mock_self = args[0]
                    msg = str(e)
                    if __mock_self.call_args is not None:
                        actual_args, actual_kwargs = __mock_self.call_args
                        introspection = ""
                        try:
                            assert actual_args == args[1:]
                        except AssertionError as e_args:
                            introspection += "\nArgs:\n" + str(e_args)
                        try:
                            assert actual_kwargs == kwargs
                        except AssertionError as e_kwargs:
                            introspection += "\nKwargs:\n" + str(e_kwargs)
                        if introspection:
                            msg += "\n\npytest introspection follows:\n" + introspection
                e = AssertionError(msg)
                e._mock_introspection_applied = True  # type:ignore[attr-defined]
    >           raise e
    E           AssertionError: expected call not found.
    E           Expected: mock('b', 2, {'jest'})
    E           Actual: mock('a', 1, {'test'})
    E
    E           pytest introspection follows:
    E
    E           Args:
    
    ../../BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:426: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    mocker = <pytest_mock.plugin.MockerFixture object at 0x7f7404503550>
    
        @pytest.mark.usefixtures("needs_assert_rewrite")
        def test_assert_called_args_with_introspection(mocker: MockerFixture) -> None:
            stub = mocker.stub()
    
            complex_args = ("a", 1, {"test"})
            wrong_args = ("b", 2, {"jest"})
    
            stub(*complex_args)
            stub.assert_called_with(*complex_args)
            stub.assert_called_once_with(*complex_args)
    
            with assert_argument_introspection(complex_args, wrong_args):
                stub.assert_called_with(*wrong_args)
    >           stub.assert_called_once_with(*wrong_args)
    
    tests/test_pytest_mock.py:584:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib64/python3.8/contextlib.py:131: in __exit__
        self.gen.throw(type, value, traceback)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    left = ('a', 1, {'test'}), right = ('b', 2, {'jest'})
    
        @contextmanager
        def assert_argument_introspection(left: Any, right: Any) -> Generator[None, None, None]:
            """
            Assert detailed argument introspection is used
            """
            try:
                yield
            except AssertionError as e:
                # this may be a bit too assuming, but seems nicer then hard-coding
                import _pytest.assertion.util as util
    
                # NOTE: we assert with either verbose or not, depending on how our own
                #       test was run by examining sys.argv
                verbose = any(a.startswith("-v") for a in sys.argv)
                expected = "\n  ".join(util._compare_eq_iterable(left, right, verbose))
    >           assert expected in str(e)
    E           assert 'Use -v to get the full diff' in "expected call not found.\nExpected: mock('b', 2, {'jest'})\nActual: mock('a', 1, {'test'})\n\npytest introspection follows:\n\nArgs:\n"
    E            +  where "expected call not found.\nExpected: mock('b', 2, {'jest'})\nActual: mock('a', 1, {'test'})\n\npytest introspection follows:\n\nArgs:\n" = str(AssertionError("expected call not found.\nExpected: mock('b', 2, {'jest'})\nActual: mock('a', 1, {'test'})\n\npytest introspection follows:\n\nArgs:\n"))
    
    tests/test_pytest_mock.py:518: AssertionError
    _______________________________________________________________ test_assert_called_kwargs_with_introspection _______________________________________________________________
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>, args = (<MagicMock spec='function' id='140136266474976'>,)
    kwargs = {'foo': {'baz': 'bran', 'goo': 1}}, __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock(foo={'goo': 1, 'baz': 'bran'})\nActual: mock(foo={'bar': 1, 'baz': 'spam'})\n\npytest introspection follows:\n\nKwargs:\n"
    __mock_self = <MagicMock spec='function' id='140136266474976'>, actual_args = (), actual_kwargs = {'foo': {'bar': 1, 'baz': 'spam'}}, introspection = '\nKwargs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
    >           __wrapped_mock_method__(*args, **kwargs)
    
    ../../BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <MagicMock spec='function' id='140136266474976'>, args = (), kwargs = {'foo': {'baz': 'bran', 'goo': 1}}
    expected = ('', <BoundArguments (kwargs={'foo': {'goo': 1, 'baz': 'bran'}})>), actual = ('', <BoundArguments (kwargs={'foo': {'bar': 1, 'baz': 'spam'}})>)
    _error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f7404609940>, cause = None
    
        def assert_called_with(self, /, *args, **kwargs):
            """assert that the last call was made with the specified arguments.
    
            Raises an AssertionError if the args and keyword args passed in are
            different to the last call to the mock."""
            if self.call_args is None:
                expected = self._format_mock_call_signature(args, kwargs)
                actual = 'not called.'
                error_message = ('expected call not found.\nExpected: %s\nActual: %s'
                        % (expected, actual))
                raise AssertionError(error_message)
    
            def _error_message():
                msg = self._format_mock_failure_message(args, kwargs)
                return msg
            expected = self._call_matcher((args, kwargs))
            actual = self._call_matcher(self.call_args)
            if expected != actual:
                cause = expected if isinstance(expected, Exception) else None
    >           raise AssertionError(_error_message()) from cause
    E           AssertionError: expected call not found.
    E           Expected: mock(foo={'goo': 1, 'baz': 'bran'})
    E           Actual: mock(foo={'bar': 1, 'baz': 'spam'})
    
    /usr/lib64/python3.8/unittest/mock.py:913: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    left = {'foo': {'bar': 1, 'baz': 'spam'}}, right = {'foo': {'baz': 'bran', 'goo': 1}}
    
        @contextmanager
        def assert_argument_introspection(left: Any, right: Any) -> Generator[None, None, None]:
            """
            Assert detailed argument introspection is used
            """
            try:
    >           yield
    
    tests/test_pytest_mock.py:509:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    mocker = <pytest_mock.plugin.MockerFixture object at 0x7f74046227f0>
    
        @pytest.mark.usefixtures("needs_assert_rewrite")
        def test_assert_called_kwargs_with_introspection(mocker: MockerFixture) -> None:
            stub = mocker.stub()
    
            complex_kwargs = dict(foo={"bar": 1, "baz": "spam"})
            wrong_kwargs = dict(foo={"goo": 1, "baz": "bran"})
    
            stub(**complex_kwargs)
            stub.assert_called_with(**complex_kwargs)
            stub.assert_called_once_with(**complex_kwargs)
    
            with assert_argument_introspection(complex_kwargs, wrong_kwargs):
    >           stub.assert_called_with(**wrong_kwargs)
    
    tests/test_pytest_mock.py:599:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    args = (<MagicMock spec='function' id='140136266474976'>,), kwargs = {'foo': {'baz': 'bran', 'goo': 1}}, __tracebackhide__ = True
    
        def wrap_assert_called_with(*args: Any, **kwargs: Any) -> None:
            __tracebackhide__ = True
    >       assert_wrapper(_mock_module_originals["assert_called_with"], *args, **kwargs)
    
    ../../BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:436:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>, args = (<MagicMock spec='function' id='140136266474976'>,)
    kwargs = {'foo': {'baz': 'bran', 'goo': 1}}, __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock(foo={'goo': 1, 'baz': 'bran'})\nActual: mock(foo={'bar': 1, 'baz': 'spam'})\n\npytest introspection follows:\n\nKwargs:\n"
    __mock_self = <MagicMock spec='function' id='140136266474976'>, actual_args = (), actual_kwargs = {'foo': {'bar': 1, 'baz': 'spam'}}, introspection = '\nKwargs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
                __wrapped_mock_method__(*args, **kwargs)
                return
            except AssertionError as e:
                if getattr(e, "_mock_introspection_applied", 0):
                    msg = str(e)
                else:
                    __mock_self = args[0]
                    msg = str(e)
                    if __mock_self.call_args is not None:
                        actual_args, actual_kwargs = __mock_self.call_args
                        introspection = ""
                        try:
                            assert actual_args == args[1:]
                        except AssertionError as e_args:
                            introspection += "\nArgs:\n" + str(e_args)
                        try:
                            assert actual_kwargs == kwargs
                        except AssertionError as e_kwargs:
                            introspection += "\nKwargs:\n" + str(e_kwargs)
                        if introspection:
                            msg += "\n\npytest introspection follows:\n" + introspection
                e = AssertionError(msg)
                e._mock_introspection_applied = True  # type:ignore[attr-defined]
    >           raise e
    E           AssertionError: expected call not found.
    E           Expected: mock(foo={'goo': 1, 'baz': 'bran'})
    E           Actual: mock(foo={'bar': 1, 'baz': 'spam'})
    E
    E           pytest introspection follows:
    E
    E           Kwargs:
    
    ../../BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:426: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    mocker = <pytest_mock.plugin.MockerFixture object at 0x7f74046227f0>
    
        @pytest.mark.usefixtures("needs_assert_rewrite")
        def test_assert_called_kwargs_with_introspection(mocker: MockerFixture) -> None:
            stub = mocker.stub()
    
            complex_kwargs = dict(foo={"bar": 1, "baz": "spam"})
            wrong_kwargs = dict(foo={"goo": 1, "baz": "bran"})
    
            stub(**complex_kwargs)
            stub.assert_called_with(**complex_kwargs)
            stub.assert_called_once_with(**complex_kwargs)
    
            with assert_argument_introspection(complex_kwargs, wrong_kwargs):
                stub.assert_called_with(**wrong_kwargs)
    >           stub.assert_called_once_with(**wrong_kwargs)
    
    tests/test_pytest_mock.py:600:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib64/python3.8/contextlib.py:131: in __exit__
        self.gen.throw(type, value, traceback)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    left = {'foo': {'bar': 1, 'baz': 'spam'}}, right = {'foo': {'baz': 'bran', 'goo': 1}}
    
        @contextmanager
        def assert_argument_introspection(left: Any, right: Any) -> Generator[None, None, None]:
            """
            Assert detailed argument introspection is used
            """
            try:
                yield
            except AssertionError as e:
                # this may be a bit too assuming, but seems nicer then hard-coding
                import _pytest.assertion.util as util
    
                # NOTE: we assert with either verbose or not, depending on how our own
                #       test was run by examining sys.argv
                verbose = any(a.startswith("-v") for a in sys.argv)
                expected = "\n  ".join(util._compare_eq_iterable(left, right, verbose))
    >           assert expected in str(e)
    E           assert 'Use -v to get the full diff' in "expected call not found.\nExpected: mock(foo={'goo': 1, 'baz': 'bran'})\nActual: mock(foo={'bar': 1, 'baz': 'spam'})\n\npytest introspection follows:\n\nKwargs:\n"
    E            +  where "expected call not found.\nExpected: mock(foo={'goo': 1, 'baz': 'bran'})\nActual: mock(foo={'bar': 1, 'baz': 'spam'})\n\npytest introspection follows:\n\nKwargs:\n" = str(AssertionError("expected call not found.\nExpected: mock(foo={'goo': 1, 'baz': 'bran'})\nActual: mock(foo={'bar': 1, 'baz': 'spam'})\n\npytest introspection follows:\n\nKwargs:\n"))
    
    tests/test_pytest_mock.py:518: AssertionError
    ___________________________________________________________________________ test_standalone_mock ___________________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-1/test_standalone_mock0')>
    
        def test_standalone_mock(testdir: Any) -> None:
            """Check that the "mock_use_standalone" is being used."""
            testdir.makepyfile(
                """
                def test_foo(mocker):
                    pass
            """
            )
            testdir.makeini(
                """
                [pytest]
                mock_use_standalone_module = true
            """
            )
            result = testdir.runpytest_subprocess()
    >       assert result.ret == 3
    E       assert <ExitCode.OK: 0> == 3
    E        +  where <ExitCode.OK: 0> = <RunResult ret=ExitCode.OK len(stdout.lines)=9 len(stderr.lines)=0 duration=2.37s>.ret
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mock-3.6.0/tests/test_pytest_mock.py:721: AssertionError
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-1/test_standalone_mock0/runpytest-0
         in: /tmp/pytest-of-tkloczko/pytest-1/test_standalone_mock0
    ============================= test session starts ==============================
    platform linux -- Python 3.8.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
    rootdir: /tmp/pytest-of-tkloczko/pytest-1/test_standalone_mock0, configfile: tox.ini
    plugins: mock-3.6.0, forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, asyncio-0.14.0, expect-1.1.0, cov-2.11.1, httpbin-1.0.0, xdist-2.2.1, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, pyfakefs-4.4.0, freezegun-0.4.2, cases-3.4.6, hypothesis-6.10.1, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, flaky-3.7.0
    collected 1 item
    
    test_standalone_mock.py .                                                [100%]
    
    ============================== 1 passed in 0.03s ===============================
    _______________________________________________________________________ test_detailed_introspection ________________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-1/test_detailed_introspection0')>
    
        @pytest.mark.usefixtures("needs_assert_rewrite")
        def test_detailed_introspection(testdir: Any) -> None:
            """Check that the "mock_use_standalone" is being used."""
            testdir.makepyfile(
                """
                def test(mocker):
                    m = mocker.Mock()
                    m('fo')
                    m.assert_called_once_with('', bar=4)
            """
            )
            result = testdir.runpytest("-s")
            if NEW_FORMATTING:
                expected_lines = [
                    "*AssertionError: expected call not found.",
                    "*Expected: mock('', bar=4)",
                    "*Actual: mock('fo')",
                ]
            else:
                expected_lines = [
                    "*AssertionError: Expected call: mock('', bar=4)*",
                    "*Actual call: mock('fo')*",
                ]
            expected_lines += [
                "*pytest introspection follows:*",
                "*Args:",
                "*assert ('fo',) == ('',)",
                "*At index 0 diff: 'fo' != ''*",
                "*Use -v to get the full diff*",
                "*Kwargs:*",
                "*assert {} == {'bar': 4}*",
                "*Right contains* more item*",
                "*{'bar': 4}*",
                "*Use -v to get the full diff*",
            ]
    >       result.stdout.fnmatch_lines(expected_lines)
    E       Failed: nomatch: '*AssertionError: expected call not found.'
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-1/test_detailed_introspection0'
    E           and: 'plugins: mock-3.6.0, forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, asyncio-0.14.0, expect-1.1.0, cov-2.11.1, httpbin-1.0.0, xdist-2.2.1, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, pyfakefs-4.4.0, freezegun-0.4.2, cases-3.4.6, hypothesis-6.10.1, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, flaky-3.7.0'
    E           and: 'collected 1 item'
    E           and: ''
    E           and: 'test_detailed_introspection.py F'
    E           and: ''
    E           and: '=================================== FAILURES ==================================='
    E           and: '_____________________________________ test _____________________________________'
    E           and: ''
    E           and: '__wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>'
    E           and: "args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E           and: 'msg = "expected call not found.\\nExpected: mock(\'\', bar=4)\\nActual: mock(\'fo\')\\n\\npytest introspection follows:\\n\\nArgs:\\n\\nKwargs:\\n"'
    E           and: "__mock_self = <Mock id='140136266498592'>, actual_args = ('fo',)"
    E           and: "actual_kwargs = {}, introspection = '\\nArgs:\\n\\nKwargs:\\n'"
    E           and: ''
    E           and: '    def assert_wrapper('
    E           and: '        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any'
    E           and: '    ) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '        try:'
    E           and: '>           __wrapped_mock_method__(*args, **kwargs)'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: "self = <Mock id='140136266498592'>, args = ('',), kwargs = {'bar': 4}"
    E           and: "expected = (('',), {'bar': 4}), actual = call('fo')"
    E           and: '_error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f7404707b80>'
    E           and: 'cause = None'
    E           and: ''
    E           and: '    def assert_called_with(self, /, *args, **kwargs):'
    E           and: '        """assert that the last call was made with the specified arguments.'
    E           and: '    '
    E           and: '        Raises an AssertionError if the args and keyword args passed in are'
    E           and: '        different to the last call to the mock."""'
    E           and: '        if self.call_args is None:'
    E           and: '            expected = self._format_mock_call_signature(args, kwargs)'
    E           and: "            actual = 'not called.'"
    E           and: "            error_message = ('expected call not found.\\nExpected: %s\\nActual: %s'"
    E           and: '                    % (expected, actual))'
    E           and: '            raise AssertionError(error_message)'
    E           and: '    '
    E           and: '        def _error_message():'
    E           and: '            msg = self._format_mock_failure_message(args, kwargs)'
    E           and: '            return msg'
    E           and: '        expected = self._call_matcher((args, kwargs))'
    E           and: '        actual = self._call_matcher(self.call_args)'
    E           and: '        if expected != actual:'
    E           and: '            cause = expected if isinstance(expected, Exception) else None'
    E           and: '>           raise AssertionError(_error_message()) from cause'
    E       fnmatch: '*AssertionError: expected call not found.'
    E          with: 'E           AssertionError: expected call not found.'
    E       fnmatch: "*Expected: mock('', bar=4)"
    E          with: "E           Expected: mock('', bar=4)"
    E       fnmatch: "*Actual: mock('fo')"
    E          with: "E           Actual: mock('fo')"
    E       nomatch: '*pytest introspection follows:*'
    E           and: ''
    E           and: '/usr/lib64/python3.8/unittest/mock.py:913: AssertionError'
    E           and: ''
    E           and: 'During handling of the above exception, another exception occurred:'
    E           and: ''
    E           and: '__wrapped_mock_method__ = <function NonCallableMock.assert_called_once_with at 0x7f759b50eb80>'
    E           and: "args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E       fnmatch: '*pytest introspection follows:*'
    E          with: 'msg = "expected call not found.\\nExpected: mock(\'\', bar=4)\\nActual: mock(\'fo\')\\n\\npytest introspection follows:\\n\\nArgs:\\n\\nKwargs:\\n"'
    E       nomatch: '*Args:'
    E           and: ''
    E           and: '    def assert_wrapper('
    E           and: '        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any'
    E           and: '    ) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '        try:'
    E           and: '>           __wrapped_mock_method__(*args, **kwargs)'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: "self = <Mock id='140136266498592'>, args = ('',), kwargs = {'bar': 4}"
    E           and: ''
    E           and: '    def assert_called_once_with(self, /, *args, **kwargs):'
    E           and: '        """assert that the mock was called exactly once and that that call was'
    E           and: '        with the specified arguments."""'
    E           and: '        if not self.call_count == 1:'
    E           and: '            msg = ("Expected \'%s\' to be called once. Called %s times.%s"'
    E           and: "                   % (self._mock_name or 'mock',"
    E           and: '                      self.call_count,'
    E           and: '                      self._calls_repr()))'
    E           and: '            raise AssertionError(msg)'
    E           and: '>       return self.assert_called_with(*args, **kwargs)'
    E           and: ''
    E           and: '/usr/lib64/python3.8/unittest/mock.py:925: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: "args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E           and: ''
    E           and: '    def wrap_assert_called_with(*args: Any, **kwargs: Any) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '>       assert_wrapper(_mock_module_originals["assert_called_with"], *args, **kwargs)'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:436: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: '__wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>'
    E           and: "args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E           and: 'msg = "expected call not found.\\nExpected: mock(\'\', bar=4)\\nActual: mock(\'fo\')\\n\\npytest introspection follows:\\n\\nArgs:\\n\\nKwargs:\\n"'
    E           and: "__mock_self = <Mock id='140136266498592'>, actual_args = ('fo',)"
    E           and: "actual_kwargs = {}, introspection = '\\nArgs:\\n\\nKwargs:\\n'"
    E           and: ''
    E           and: '    def assert_wrapper('
    E           and: '        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any'
    E           and: '    ) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '        try:'
    E           and: '            __wrapped_mock_method__(*args, **kwargs)'
    E           and: '            return'
    E           and: '        except AssertionError as e:'
    E           and: '            if getattr(e, "_mock_introspection_applied", 0):'
    E           and: '                msg = str(e)'
    E           and: '            else:'
    E           and: '                __mock_self = args[0]'
    E           and: '                msg = str(e)'
    E           and: '                if __mock_self.call_args is not None:'
    E           and: '                    actual_args, actual_kwargs = __mock_self.call_args'
    E           and: '                    introspection = ""'
    E           and: '                    try:'
    E           and: '                        assert actual_args == args[1:]'
    E           and: '                    except AssertionError as e_args:'
    E           and: '                        introspection += "\\nArgs:\\n" + str(e_args)'
    E           and: '                    try:'
    E           and: '                        assert actual_kwargs == kwargs'
    E           and: '                    except AssertionError as e_kwargs:'
    E           and: '                        introspection += "\\nKwargs:\\n" + str(e_kwargs)'
    E           and: '                    if introspection:'
    E           and: '                        msg += "\\n\\npytest introspection follows:\\n" + introspection'
    E           and: '            e = AssertionError(msg)'
    E           and: '            e._mock_introspection_applied = True  # type:ignore[attr-defined]'
    E           and: '>           raise e'
    E           and: 'E           AssertionError: expected call not found.'
    E           and: "E           Expected: mock('', bar=4)"
    E           and: "E           Actual: mock('fo')"
    E           and: 'E           '
    E           and: 'E           pytest introspection follows:'
    E           and: 'E           '
    E       fnmatch: '*Args:'
    E          with: 'E           Args:'
    E       nomatch: "*assert ('fo',) == ('',)"
    E           and: 'E           '
    E           and: 'E           Kwargs:'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:426: AssertionError'
    E           and: ''
    E           and: 'During handling of the above exception, another exception occurred:'
    E           and: ''
    E           and: 'mocker = <pytest_mock.plugin.MockerFixture object at 0x7f7404628e20>'
    E           and: ''
    E           and: '    def test(mocker):'
    E           and: '        m = mocker.Mock()'
    E           and: "        m('fo')"
    E           and: ">       m.assert_called_once_with('', bar=4)"
    E           and: 'E       AssertionError: expected call not found.'
    E           and: "E       Expected: mock('', bar=4)"
    E           and: "E       Actual: mock('fo')"
    E           and: 'E       '
    E           and: 'E       pytest introspection follows:'
    E           and: 'E       '
    E           and: 'E       Args:'
    E           and: 'E       '
    E           and: 'E       Kwargs:'
    E           and: ''
    E           and: 'test_detailed_introspection.py:4: AssertionError'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_detailed_introspection.py::test - AssertionError: expected call n...'
    E           and: '============================== 1 failed in 0.12s ==============================='
    E       remains unmatched: "*assert ('fo',) == ('',)"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mock-3.6.0/tests/test_pytest_mock.py:760: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    ============================= test session starts ==============================
    platform linux -- Python 3.8.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
    rootdir: /tmp/pytest-of-tkloczko/pytest-1/test_detailed_introspection0
    plugins: mock-3.6.0, forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, asyncio-0.14.0, expect-1.1.0, cov-2.11.1, httpbin-1.0.0, xdist-2.2.1, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, pyfakefs-4.4.0, freezegun-0.4.2, cases-3.4.6, hypothesis-6.10.1, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, flaky-3.7.0
    collected 1 item
    
    test_detailed_introspection.py F
    
    =================================== FAILURES ===================================
    _____________________________________ test _____________________________________
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>
    args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock('', bar=4)\nActual: mock('fo')\n\npytest introspection follows:\n\nArgs:\n\nKwargs:\n"
    __mock_self = <Mock id='140136266498592'>, actual_args = ('fo',)
    actual_kwargs = {}, introspection = '\nArgs:\n\nKwargs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
    >           __wrapped_mock_method__(*args, **kwargs)
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <Mock id='140136266498592'>, args = ('',), kwargs = {'bar': 4}
    expected = (('',), {'bar': 4}), actual = call('fo')
    _error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f7404707b80>
    cause = None
    
        def assert_called_with(self, /, *args, **kwargs):
            """assert that the last call was made with the specified arguments.
    
            Raises an AssertionError if the args and keyword args passed in are
            different to the last call to the mock."""
            if self.call_args is None:
                expected = self._format_mock_call_signature(args, kwargs)
                actual = 'not called.'
                error_message = ('expected call not found.\nExpected: %s\nActual: %s'
                        % (expected, actual))
                raise AssertionError(error_message)
    
            def _error_message():
                msg = self._format_mock_failure_message(args, kwargs)
                return msg
            expected = self._call_matcher((args, kwargs))
            actual = self._call_matcher(self.call_args)
            if expected != actual:
                cause = expected if isinstance(expected, Exception) else None
    >           raise AssertionError(_error_message()) from cause
    E           AssertionError: expected call not found.
    E           Expected: mock('', bar=4)
    E           Actual: mock('fo')
    
    /usr/lib64/python3.8/unittest/mock.py:913: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_once_with at 0x7f759b50eb80>
    args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock('', bar=4)\nActual: mock('fo')\n\npytest introspection follows:\n\nArgs:\n\nKwargs:\n"
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
    >           __wrapped_mock_method__(*args, **kwargs)
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <Mock id='140136266498592'>, args = ('',), kwargs = {'bar': 4}
    
        def assert_called_once_with(self, /, *args, **kwargs):
            """assert that the mock was called exactly once and that that call was
            with the specified arguments."""
            if not self.call_count == 1:
                msg = ("Expected '%s' to be called once. Called %s times.%s"
                       % (self._mock_name or 'mock',
                          self.call_count,
                          self._calls_repr()))
                raise AssertionError(msg)
    >       return self.assert_called_with(*args, **kwargs)
    
    /usr/lib64/python3.8/unittest/mock.py:925:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    
        def wrap_assert_called_with(*args: Any, **kwargs: Any) -> None:
            __tracebackhide__ = True
    >       assert_wrapper(_mock_module_originals["assert_called_with"], *args, **kwargs)
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:436:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    __wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x7f759b50eaf0>
    args = (<Mock id='140136266498592'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    msg = "expected call not found.\nExpected: mock('', bar=4)\nActual: mock('fo')\n\npytest introspection follows:\n\nArgs:\n\nKwargs:\n"
    __mock_self = <Mock id='140136266498592'>, actual_args = ('fo',)
    actual_kwargs = {}, introspection = '\nArgs:\n\nKwargs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
                __wrapped_mock_method__(*args, **kwargs)
                return
            except AssertionError as e:
                if getattr(e, "_mock_introspection_applied", 0):
                    msg = str(e)
                else:
                    __mock_self = args[0]
                    msg = str(e)
                    if __mock_self.call_args is not None:
                        actual_args, actual_kwargs = __mock_self.call_args
                        introspection = ""
                        try:
                            assert actual_args == args[1:]
                        except AssertionError as e_args:
                            introspection += "\nArgs:\n" + str(e_args)
                        try:
                            assert actual_kwargs == kwargs
                        except AssertionError as e_kwargs:
                            introspection += "\nKwargs:\n" + str(e_kwargs)
                        if introspection:
                            msg += "\n\npytest introspection follows:\n" + introspection
                e = AssertionError(msg)
                e._mock_introspection_applied = True  # type:ignore[attr-defined]
    >           raise e
    E           AssertionError: expected call not found.
    E           Expected: mock('', bar=4)
    E           Actual: mock('fo')
    E
    E           pytest introspection follows:
    E
    E           Args:
    E
    E           Kwargs:
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:426: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    mocker = <pytest_mock.plugin.MockerFixture object at 0x7f7404628e20>
    
        def test(mocker):
            m = mocker.Mock()
            m('fo')
    >       m.assert_called_once_with('', bar=4)
    E       AssertionError: expected call not found.
    E       Expected: mock('', bar=4)
    E       Actual: mock('fo')
    E
    E       pytest introspection follows:
    E
    E       Args:
    E
    E       Kwargs:
    
    test_detailed_introspection.py:4: AssertionError
    =========================== short test summary info ============================
    FAILED test_detailed_introspection.py::test - AssertionError: expected call n...
    ============================== 1 failed in 0.12s ===============================
    ____________________________________________________________________ test_detailed_introspection_async _____________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-1/test_detailed_introspection_async0')>
    
        @pytest.mark.skipif(
            sys.version_info < (3, 8), reason="AsyncMock is present on 3.8 and above"
        )
        @pytest.mark.usefixtures("needs_assert_rewrite")
        def test_detailed_introspection_async(testdir: Any) -> None:
            """Check that the "mock_use_standalone" is being used."""
            testdir.makepyfile(
                """
                import pytest
    
                @pytest.mark.asyncio
                async def test(mocker):
                    m = mocker.AsyncMock()
                    await m('fo')
                    m.assert_awaited_once_with('', bar=4)
            """
            )
            result = testdir.runpytest("-s")
            expected_lines = [
                "*AssertionError: expected await not found.",
                "*Expected: mock('', bar=4)",
                "*Actual: mock('fo')",
                "*pytest introspection follows:*",
                "*Args:",
                "*assert ('fo',) == ('',)",
                "*At index 0 diff: 'fo' != ''*",
                "*Use -v to get the full diff*",
                "*Kwargs:*",
                "*assert {} == {'bar': 4}*",
                "*Right contains* more item*",
                "*{'bar': 4}*",
                "*Use -v to get the full diff*",
            ]
    >       result.stdout.fnmatch_lines(expected_lines)
    E       Failed: nomatch: '*AssertionError: expected await not found.'
    E           and: '============================= test session starts =============================='
    E           and: 'platform linux -- Python 3.8.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1'
    E           and: 'rootdir: /tmp/pytest-of-tkloczko/pytest-1/test_detailed_introspection_async0'
    E           and: 'plugins: mock-3.6.0, forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, asyncio-0.14.0, expect-1.1.0, cov-2.11.1, httpbin-1.0.0, xdist-2.2.1, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, pyfakefs-4.4.0, freezegun-0.4.2, cases-3.4.6, hypothesis-6.10.1, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, flaky-3.7.0'
    E           and: 'collected 1 item'
    E           and: ''
    E           and: 'test_detailed_introspection_async.py F'
    E           and: ''
    E           and: '=================================== FAILURES ==================================='
    E           and: '_____________________________________ test _____________________________________'
    E           and: ''
    E           and: '__wrapped_mock_method__ = <function AsyncMockMixin.assert_awaited_with at 0x7f759b5173a0>'
    E           and: "args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E           and: 'msg = "expected await not found.\\nExpected: mock(\'\', bar=4)\\nActual: mock(\'fo\')\\n\\npytest introspection follows:\\n\\nArgs:\\n\\nKwargs:\\n"'
    E           and: "__mock_self = <AsyncMock id='140136262204192'>, actual_args = ('fo',)"
    E           and: "actual_kwargs = {}, introspection = '\\nArgs:\\n\\nKwargs:\\n'"
    E           and: ''
    E           and: '    def assert_wrapper('
    E           and: '        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any'
    E           and: '    ) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '        try:'
    E           and: '>           __wrapped_mock_method__(*args, **kwargs)'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: "self = <AsyncMock id='140136262204192'>, args = ('',), kwargs = {'bar': 4}"
    E           and: "expected = (('',), {'bar': 4})"
    E           and: '_error_message = <function AsyncMockMixin.assert_awaited_with.<locals>._error_message at 0x7f740475e310>'
    E           and: "actual = call('fo'), cause = None"
    E           and: ''
    E           and: '    def assert_awaited_with(self, /, *args, **kwargs):'
    E           and: '        """'
    E           and: '        Assert that the last await was with the specified arguments.'
    E           and: '        """'
    E           and: '        if self.await_args is None:'
    E           and: '            expected = self._format_mock_call_signature(args, kwargs)'
    E           and: "            raise AssertionError(f'Expected await: {expected}\\nNot awaited')"
    E           and: '    '
    E           and: '        def _error_message():'
    E           and: "            msg = self._format_mock_failure_message(args, kwargs, action='await')"
    E           and: '            return msg'
    E           and: '    '
    E           and: '        expected = self._call_matcher((args, kwargs))'
    E           and: '        actual = self._call_matcher(self.await_args)'
    E           and: '        if expected != actual:'
    E           and: '            cause = expected if isinstance(expected, Exception) else None'
    E           and: '>           raise AssertionError(_error_message()) from cause'
    E       fnmatch: '*AssertionError: expected await not found.'
    E          with: 'E           AssertionError: expected await not found.'
    E       fnmatch: "*Expected: mock('', bar=4)"
    E          with: "E           Expected: mock('', bar=4)"
    E       fnmatch: "*Actual: mock('fo')"
    E          with: "E           Actual: mock('fo')"
    E       nomatch: '*pytest introspection follows:*'
    E           and: ''
    E           and: '/usr/lib64/python3.8/unittest/mock.py:2186: AssertionError'
    E           and: ''
    E           and: 'During handling of the above exception, another exception occurred:'
    E           and: ''
    E           and: '__wrapped_mock_method__ = <function AsyncMockMixin.assert_awaited_once_with at 0x7f759b517430>'
    E           and: "args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E       fnmatch: '*pytest introspection follows:*'
    E          with: 'msg = "expected await not found.\\nExpected: mock(\'\', bar=4)\\nActual: mock(\'fo\')\\n\\npytest introspection follows:\\n\\nArgs:\\n\\nKwargs:\\n"'
    E       nomatch: '*Args:'
    E           and: ''
    E           and: '    def assert_wrapper('
    E           and: '        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any'
    E           and: '    ) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '        try:'
    E           and: '>           __wrapped_mock_method__(*args, **kwargs)'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: "self = <AsyncMock id='140136262204192'>, args = ('',), kwargs = {'bar': 4}"
    E           and: ''
    E           and: '    def assert_awaited_once_with(self, /, *args, **kwargs):'
    E           and: '        """'
    E           and: '        Assert that the mock was awaited exactly once and with the specified'
    E           and: '        arguments.'
    E           and: '        """'
    E           and: '        if not self.await_count == 1:'
    E           and: '            msg = (f"Expected {self._mock_name or \'mock\'} to have been awaited once."'
    E           and: '                   f" Awaited {self.await_count} times.")'
    E           and: '            raise AssertionError(msg)'
    E           and: '>       return self.assert_awaited_with(*args, **kwargs)'
    E           and: ''
    E           and: '/usr/lib64/python3.8/unittest/mock.py:2197: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: "args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E           and: ''
    E           and: '    def wrap_assert_awaited_with(*args: Any, **kwargs: Any) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '>       assert_wrapper(_mock_module_originals["assert_awaited_with"], *args, **kwargs)'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:471: '
    E           and: '_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ '
    E           and: ''
    E           and: '__wrapped_mock_method__ = <function AsyncMockMixin.assert_awaited_with at 0x7f759b5173a0>'
    E           and: "args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}"
    E           and: '__tracebackhide__ = True'
    E           and: 'msg = "expected await not found.\\nExpected: mock(\'\', bar=4)\\nActual: mock(\'fo\')\\n\\npytest introspection follows:\\n\\nArgs:\\n\\nKwargs:\\n"'
    E           and: "__mock_self = <AsyncMock id='140136262204192'>, actual_args = ('fo',)"
    E           and: "actual_kwargs = {}, introspection = '\\nArgs:\\n\\nKwargs:\\n'"
    E           and: ''
    E           and: '    def assert_wrapper('
    E           and: '        __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any'
    E           and: '    ) -> None:'
    E           and: '        __tracebackhide__ = True'
    E           and: '        try:'
    E           and: '            __wrapped_mock_method__(*args, **kwargs)'
    E           and: '            return'
    E           and: '        except AssertionError as e:'
    E           and: '            if getattr(e, "_mock_introspection_applied", 0):'
    E           and: '                msg = str(e)'
    E           and: '            else:'
    E           and: '                __mock_self = args[0]'
    E           and: '                msg = str(e)'
    E           and: '                if __mock_self.call_args is not None:'
    E           and: '                    actual_args, actual_kwargs = __mock_self.call_args'
    E           and: '                    introspection = ""'
    E           and: '                    try:'
    E           and: '                        assert actual_args == args[1:]'
    E           and: '                    except AssertionError as e_args:'
    E           and: '                        introspection += "\\nArgs:\\n" + str(e_args)'
    E           and: '                    try:'
    E           and: '                        assert actual_kwargs == kwargs'
    E           and: '                    except AssertionError as e_kwargs:'
    E           and: '                        introspection += "\\nKwargs:\\n" + str(e_kwargs)'
    E           and: '                    if introspection:'
    E           and: '                        msg += "\\n\\npytest introspection follows:\\n" + introspection'
    E           and: '            e = AssertionError(msg)'
    E           and: '            e._mock_introspection_applied = True  # type:ignore[attr-defined]'
    E           and: '>           raise e'
    E           and: 'E           AssertionError: expected await not found.'
    E           and: "E           Expected: mock('', bar=4)"
    E           and: "E           Actual: mock('fo')"
    E           and: 'E           '
    E           and: 'E           pytest introspection follows:'
    E           and: 'E           '
    E       fnmatch: '*Args:'
    E          with: 'E           Args:'
    E       nomatch: "*assert ('fo',) == ('',)"
    E           and: 'E           '
    E           and: 'E           Kwargs:'
    E           and: ''
    E           and: '/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:426: AssertionError'
    E           and: ''
    E           and: 'During handling of the above exception, another exception occurred:'
    E           and: ''
    E           and: 'mocker = <pytest_mock.plugin.MockerFixture object at 0x7f740420fa30>'
    E           and: ''
    E           and: '    @pytest.mark.asyncio'
    E           and: '    async def test(mocker):'
    E           and: '        m = mocker.AsyncMock()'
    E           and: "        await m('fo')"
    E           and: ">       m.assert_awaited_once_with('', bar=4)"
    E           and: 'E       AssertionError: expected await not found.'
    E           and: "E       Expected: mock('', bar=4)"
    E           and: "E       Actual: mock('fo')"
    E           and: 'E       '
    E           and: 'E       pytest introspection follows:'
    E           and: 'E       '
    E           and: 'E       Args:'
    E           and: 'E       '
    E           and: 'E       Kwargs:'
    E           and: ''
    E           and: 'test_detailed_introspection_async.py:7: AssertionError'
    E           and: '=========================== short test summary info ============================'
    E           and: 'FAILED test_detailed_introspection_async.py::test - AssertionError: expected ...'
    E           and: '============================== 1 failed in 0.19s ==============================='
    E       remains unmatched: "*assert ('fo',) == ('',)"
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mock-3.6.0/tests/test_pytest_mock.py:796: Failed
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    ============================= test session starts ==============================
    platform linux -- Python 3.8.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
    rootdir: /tmp/pytest-of-tkloczko/pytest-1/test_detailed_introspection_async0
    plugins: mock-3.6.0, forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, asyncio-0.14.0, expect-1.1.0, cov-2.11.1, httpbin-1.0.0, xdist-2.2.1, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, pyfakefs-4.4.0, freezegun-0.4.2, cases-3.4.6, hypothesis-6.10.1, case-1.5.3, isort-1.3.0, aspectlib-1.5.2, flaky-3.7.0
    collected 1 item
    
    test_detailed_introspection_async.py F
    
    =================================== FAILURES ===================================
    _____________________________________ test _____________________________________
    
    __wrapped_mock_method__ = <function AsyncMockMixin.assert_awaited_with at 0x7f759b5173a0>
    args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    msg = "expected await not found.\nExpected: mock('', bar=4)\nActual: mock('fo')\n\npytest introspection follows:\n\nArgs:\n\nKwargs:\n"
    __mock_self = <AsyncMock id='140136262204192'>, actual_args = ('fo',)
    actual_kwargs = {}, introspection = '\nArgs:\n\nKwargs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
    >           __wrapped_mock_method__(*args, **kwargs)
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <AsyncMock id='140136262204192'>, args = ('',), kwargs = {'bar': 4}
    expected = (('',), {'bar': 4})
    _error_message = <function AsyncMockMixin.assert_awaited_with.<locals>._error_message at 0x7f740475e310>
    actual = call('fo'), cause = None
    
        def assert_awaited_with(self, /, *args, **kwargs):
            """
            Assert that the last await was with the specified arguments.
            """
            if self.await_args is None:
                expected = self._format_mock_call_signature(args, kwargs)
                raise AssertionError(f'Expected await: {expected}\nNot awaited')
    
            def _error_message():
                msg = self._format_mock_failure_message(args, kwargs, action='await')
                return msg
    
            expected = self._call_matcher((args, kwargs))
            actual = self._call_matcher(self.await_args)
            if expected != actual:
                cause = expected if isinstance(expected, Exception) else None
    >           raise AssertionError(_error_message()) from cause
    E           AssertionError: expected await not found.
    E           Expected: mock('', bar=4)
    E           Actual: mock('fo')
    
    /usr/lib64/python3.8/unittest/mock.py:2186: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    __wrapped_mock_method__ = <function AsyncMockMixin.assert_awaited_once_with at 0x7f759b517430>
    args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    msg = "expected await not found.\nExpected: mock('', bar=4)\nActual: mock('fo')\n\npytest introspection follows:\n\nArgs:\n\nKwargs:\n"
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
    >           __wrapped_mock_method__(*args, **kwargs)
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:403:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <AsyncMock id='140136262204192'>, args = ('',), kwargs = {'bar': 4}
    
        def assert_awaited_once_with(self, /, *args, **kwargs):
            """
            Assert that the mock was awaited exactly once and with the specified
            arguments.
            """
            if not self.await_count == 1:
                msg = (f"Expected {self._mock_name or 'mock'} to have been awaited once."
                       f" Awaited {self.await_count} times.")
                raise AssertionError(msg)
    >       return self.assert_awaited_with(*args, **kwargs)
    
    /usr/lib64/python3.8/unittest/mock.py:2197:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    
        def wrap_assert_awaited_with(*args: Any, **kwargs: Any) -> None:
            __tracebackhide__ = True
    >       assert_wrapper(_mock_module_originals["assert_awaited_with"], *args, **kwargs)
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:471:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    __wrapped_mock_method__ = <function AsyncMockMixin.assert_awaited_with at 0x7f759b5173a0>
    args = (<AsyncMock id='140136262204192'>, ''), kwargs = {'bar': 4}
    __tracebackhide__ = True
    msg = "expected await not found.\nExpected: mock('', bar=4)\nActual: mock('fo')\n\npytest introspection follows:\n\nArgs:\n\nKwargs:\n"
    __mock_self = <AsyncMock id='140136262204192'>, actual_args = ('fo',)
    actual_kwargs = {}, introspection = '\nArgs:\n\nKwargs:\n'
    
        def assert_wrapper(
            __wrapped_mock_method__: Callable[..., Any], *args: Any, **kwargs: Any
        ) -> None:
            __tracebackhide__ = True
            try:
                __wrapped_mock_method__(*args, **kwargs)
                return
            except AssertionError as e:
                if getattr(e, "_mock_introspection_applied", 0):
                    msg = str(e)
                else:
                    __mock_self = args[0]
                    msg = str(e)
                    if __mock_self.call_args is not None:
                        actual_args, actual_kwargs = __mock_self.call_args
                        introspection = ""
                        try:
                            assert actual_args == args[1:]
                        except AssertionError as e_args:
                            introspection += "\nArgs:\n" + str(e_args)
                        try:
                            assert actual_kwargs == kwargs
                        except AssertionError as e_kwargs:
                            introspection += "\nKwargs:\n" + str(e_kwargs)
                        if introspection:
                            msg += "\n\npytest introspection follows:\n" + introspection
                e = AssertionError(msg)
                e._mock_introspection_applied = True  # type:ignore[attr-defined]
    >           raise e
    E           AssertionError: expected await not found.
    E           Expected: mock('', bar=4)
    E           Actual: mock('fo')
    E
    E           pytest introspection follows:
    E
    E           Args:
    E
    E           Kwargs:
    
    /home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py:426: AssertionError
    
    During handling of the above exception, another exception occurred:
    
    mocker = <pytest_mock.plugin.MockerFixture object at 0x7f740420fa30>
    
        @pytest.mark.asyncio
        async def test(mocker):
            m = mocker.AsyncMock()
            await m('fo')
    >       m.assert_awaited_once_with('', bar=4)
    E       AssertionError: expected await not found.
    E       Expected: mock('', bar=4)
    E       Actual: mock('fo')
    E
    E       pytest introspection follows:
    E
    E       Args:
    E
    E       Kwargs:
    
    test_detailed_introspection_async.py:7: AssertionError
    =========================== short test summary info ============================
    FAILED test_detailed_introspection_async.py::test - AssertionError: expected ...
    ============================== 1 failed in 0.19s ===============================
    ========================================================================= short test summary info ==========================================================================
    FAILED tests/test_pytest_mock.py::test_assert_called_args_with_introspection - assert 'Use -v to get the full diff' in "expected call not found.\nExpected: mock('b', 2, ...
    FAILED tests/test_pytest_mock.py::test_assert_called_kwargs_with_introspection - assert 'Use -v to get the full diff' in "expected call not found.\nExpected: mock(foo={'...
    FAILED tests/test_pytest_mock.py::test_standalone_mock - assert <ExitCode.OK: 0> == 3
    FAILED tests/test_pytest_mock.py::test_detailed_introspection - Failed: nomatch: '*AssertionError: expected call not found.'
    FAILED tests/test_pytest_mock.py::test_detailed_introspection_async - Failed: nomatch: '*AssertionError: expected await not found.'
    ====================================================================== 5 failed, 67 passed in 25.28s =======================================================================
    
    opened by kloczek 12
  • Major version increase?

    Major version increase?

    Hi,

    I've seen 3.3.0 changed name from MockFixture to MockerFixture. It broke existing code like in: https://github.com/staticdev/toml-validator/pull/157/checks?check_run_id=1020396590

    I see at least two possible solutions here: increasing the major version to 4.0.0 to semantically say it broke original API or rename back (maybe even creating some alias to support both names).

    opened by staticdev 12
  • 3.7.0: pytest is failing in `tests/test_pytest_mock.py::test_standalone_mock` unit

    3.7.0: pytest is failing in `tests/test_pytest_mock.py::test_standalone_mock` unit

    I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

    • python3 -sBm build -w --no-isolation
    • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
    • install .whl file in </install/prefix>
    • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

    Here is pytest output:

    + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.7.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.7.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
    + /usr/bin/pytest -ra -p no:relaxed
    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /home/tkloczko/rpmbuild/BUILD/pytest-mock-3.7.0, configfile: tox.ini
    plugins: mock-3.7.0, cov-3.0.0, asyncio-0.17.2
    asyncio: mode=auto
    collected 72 items
    
    tests/test_pytest_mock.py .........................................................F..............                                                                   [100%]
    
    ================================================================================= FAILURES =================================================================================
    ___________________________________________________________________________ test_standalone_mock ___________________________________________________________________________
    
    testdir = <Testdir local('/tmp/pytest-of-tkloczko/pytest-2/test_standalone_mock0')>
    
        def test_standalone_mock(testdir: Any) -> None:
            """Check that the "mock_use_standalone" is being used."""
            testdir.makepyfile(
                """
                def test_foo(mocker):
                    pass
            """
            )
            testdir.makeini(
                """
                [pytest]
                mock_use_standalone_module = true
            """
            )
            result = testdir.runpytest_subprocess()
    >       assert result.ret == 3
    E       assert <ExitCode.OK: 0> == 3
    E        +  where <ExitCode.OK: 0> = <RunResult ret=ExitCode.OK len(stdout.lines)=20 len(stderr.lines)=0 duration=0.46s>.ret
    
    /home/tkloczko/rpmbuild/BUILD/pytest-mock-3.7.0/tests/test_pytest_mock.py:723: AssertionError
    --------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------
    running: /usr/bin/python3 -mpytest --basetemp=/tmp/pytest-of-tkloczko/pytest-2/test_standalone_mock0/runpytest-0
         in: /tmp/pytest-of-tkloczko/pytest-2/test_standalone_mock0
    ============================= test session starts ==============================
    platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
    rootdir: /tmp/pytest-of-tkloczko/pytest-2/test_standalone_mock0, configfile: tox.ini
    plugins: mock-3.7.0, cov-3.0.0, asyncio-0.17.2
    asyncio: mode=legacy
    collected 1 item
    
    test_standalone_mock.py .                                                [100%]
    
    =============================== warnings summary ===============================
    ../../../../usr/lib/python3.8/site-packages/pytest_asyncio/plugin.py:191
      /usr/lib/python3.8/site-packages/pytest_asyncio/plugin.py:191: DeprecationWarning: The 'asyncio_mode' default value will change to 'strict' in future, please explicitly use 'asyncio_mode=strict' or 'asyncio_mode=auto' in pytest configuration file.
        config.issue_config_time_warning(LEGACY_MODE, stacklevel=2)
    
    test_standalone_mock.py::test_foo
      /usr/lib/python3.8/site-packages/pytest_asyncio/plugin.py:317: DeprecationWarning: '@pytest.fixture' is applied to <fixture _mocker, file=/home/tkloczko/rpmbuild/BUILDROOT/python-pytest-mock-3.7.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/pytest_mock/plugin.py, line=388> in 'legacy' mode, please replace it with '@pytest_asyncio.fixture' as a preparation for switching to 'strict' mode (or use 'auto' mode to seamlessly handle all these fixtures as asyncio-driven).
        warnings.warn(
    
    -- Docs: https://docs.pytest.org/en/stable/warnings.html
    ======================== 1 passed, 2 warnings in 0.03s =========================
    ========================================================================= short test summary info ==========================================================================
    FAILED tests/test_pytest_mock.py::test_standalone_mock - assert <ExitCode.OK: 0> == 3
    ======================================================================= 1 failed, 71 passed in 6.16s =======================================================================
    /usr/lib/python3.8/site-packages/_pytest/pathlib.py:80: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-6f5bceaa-27c1-4828-a3c4-0d1d4c62f501
    <class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-6f5bceaa-27c1-4828-a3c4-0d1d4c62f501'
      warnings.warn(
    /usr/lib/python3.8/site-packages/_pytest/pathlib.py:80: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-f0b2eb80-1df2-41e3-b9c6-7ae4bdb46198
    <class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-f0b2eb80-1df2-41e3-b9c6-7ae4bdb46198'
      warnings.warn(
    /usr/lib/python3.8/site-packages/_pytest/pathlib.py:80: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-aa20aba2-7e0e-4ebb-8719-a5e007e0d1c4
    <class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-aa20aba2-7e0e-4ebb-8719-a5e007e0d1c4'
      warnings.warn(
    /usr/lib/python3.8/site-packages/_pytest/pathlib.py:80: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-d429fee2-5f3d-428e-92a2-6e0fc3e29972
    <class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-d429fee2-5f3d-428e-92a2-6e0fc3e29972'
      warnings.warn(
    /usr/lib/python3.8/site-packages/_pytest/pathlib.py:80: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-0e7d96b3-02dc-4fec-88d8-b31f111ddb5d
    <class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-0e7d96b3-02dc-4fec-88d8-b31f111ddb5d'
      warnings.warn(
    /usr/lib/python3.8/site-packages/_pytest/pathlib.py:80: PytestWarning: (rm_rf) error removing /tmp/pytest-of-tkloczko/garbage-9f197e27-3fb6-4540-9abc-37cc28021b4e
    <class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-tkloczko/garbage-9f197e27-3fb6-4540-9abc-37cc28021b4e'
      warnings.warn(
    
    opened by kloczek 11
  • Stop Iteration Error

    Stop Iteration Error

    • I have the following TestGenerateAaliDict class that contains 2 tests.
    • Each of the test contained in the class will pass if run individually (comment the others)
    • Whenever I run them together, regardless of how I arrange the order, the first test will pass and the second will throw a StopIteration error.
    • This StopIteration error I get is commonly triggered when a side effect is called more than len(side_effect).
    • It seems mocks are leaking from one test to another. Even though I tried with resetting mocks at the end of each test with reset_mock():
    # Reset
    children_mock.reset_mock()
    aali_get_mock.reset_mock()
    

    and with manual resets:

    # Reset
    children_mock.side_effect = mocker.DEFAULT
    children_mock.return_value = mocker.DEFAULT
    aali_get_mock.side_effect = mocker.DEFAULT
    aali_get_mock.return_value = mocker.DEFAULT
    

    Here are the test files:

    from pytest_mock import MockerFixture
    from model_bakery import baker
    from django_mock_queries.query import MockSet, MockModel
    
    from areas.utils.logic import generate_aali_dict
    from areas.models import AALI
    
    
    class TestGenerateAaliDict:
    
        aali_1 = baker.prepare(AALI, aalia=None, id=1)
        aali_2 = baker.prepare(AALI, aalia=aali_1, id=2, aalia_id=aali_1.id)
        aali_3 = baker.prepare(AALI, aalia=aali_2, id=3, aalia_id=aali_2.id)
        aali_4 = baker.prepare(AALI, aalia=aali_3, id=4, aalia_id=aali_3.id)
        aali_5 = baker.prepare(AALI, aalia=aali_4, id=5, aalia_id=aali_4.id)
    
        def test_aali_has_only_children(self, mocker: MockerFixture):
            # Mock
            children_mock = mocker.Mock()
            children_mock.return_value.return_value.count.side_effect = [1] * 4 + [0]
            mocker.patch(
                'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager',
                children_mock
            )
            aali_get_mock = mocker.Mock()
            aali_get_mock.get.side_effect = (self.aali_1, self.aali_2, self.aali_3, self.aali_4, self.aali_5)
            mocker.patch(
                'areas.models.AALI.objects',
                aali_get_mock
            )
            # Assert
            assert generate_aali_dict(1) == {
                "aali-1": 1,
                "aali-2": 2,
                "aali-3": 3,
                "aali-4": 4,
                "aali-5": 5,
            }
            
        def test_aali_has_only_parent(self, mocker: MockerFixture):
            # Mock
            aali_get_mock = mocker.Mock()
            aali_get_mock.get.return_value = self.aali_5
            mocker.patch(
                'areas.models.AALI.objects',
                aali_get_mock
            )
            children_mock = mocker.Mock()
            children_mock.return_value.return_value.count.return_value = 0
            mocker.patch(
                'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager',
                children_mock
            )
            # Assert
            assert generate_aali_dict(5) == {
                "aali-1": 1,
                "aali-2": 2,
                "aali-3": 3,
                "aali-4": 4,
                "aali-5": 5,
            }
    
        def test_aali_has_parent_and_children(self, mocker):
            # Mock
            children_mock = mocker.Mock()
            children_mock.return_value.return_value.count.side_effect = [1] * 2 + [0]
            mocker.patch(
                'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager',
                children_mock
            )
            aali_get_mock = mocker.Mock()
            aali_get_mock.get.side_effect = (self.aali_3, self.aali_4, self.aali_5)
            mocker.patch(
                'areas.models.AALI.objects',
                aali_get_mock
            )
            # Assert
            assert generate_aali_dict(3) == {
                "aali-1": 1,
                "aali-2": 2,
                "aali-3": 3,
                "aali-4": 4,
                "aali-5": 5,
            }
    

    Here's the full traceback:

    _____________________________________________________________________ TestGenerateAaliDict.test_aali_has_only_parent ______________________________________________________________________
    
    self = <test_areas.test_utils.TestGenerateAaliDict object at 0x7fe559819db0>, mocker = <pytest_mock.plugin.MockerFixture object at 0x7fe559255150>
    
        def test_aali_has_only_parent(self, mocker: MockerFixture):
            # Mock
            aali_get_mock = mocker.Mock()
            aali_get_mock.get.return_value = self.aali_5
            mocker.patch(
                'areas.models.AALI.objects',
                aali_get_mock
            )
            children_mock = mocker.MagicMock()
            children_mock.return_value.return_value.count.return_value = 0
            mocker.patch(
                'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager',
                children_mock
            )
            # Assert
    >       assert generate_aali_dict(5) == {
                "aali-1": 1,
                "aali-2": 2,
                "aali-3": 3,
                "aali-4": 4,
                "aali-5": 5,
            }
    
    tests/test_areas/test_utils.py:56: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    areas/utils/logic.py:15: in generate_aali_dict
        while aali.children.count() > 0:
    /usr/local/lib/python3.10/unittest/mock.py:1104: in __call__
        return self._mock_call(*args, **kwargs)
    /usr/local/lib/python3.10/unittest/mock.py:1108: in _mock_call
        return self._execute_mock_call(*args, **kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <MagicMock name='mock()().count' id='140623019748960'>, args = (), kwargs = {}, effect = <list_iterator object at 0x7fe559240d00>
    
        def _execute_mock_call(self, /, *args, **kwargs):
            # separate from _increment_mock_call so that awaited functions are
            # executed separately from their call, also AsyncMock overrides this method
        
            effect = self.side_effect
            if effect is not None:
                if _is_exception(effect):
                    raise effect
                elif not _callable(effect):
    >               result = next(effect)
    E               StopIteration
    
    /usr/local/lib/python3.10/unittest/mock.py:1165: StopIteration
    ==================================================================================== warnings summary =====================================================================================
    ../usr/local/lib/python3.10/site-packages/django/utils/version.py:6
      /usr/local/lib/python3.10/site-packages/django/utils/version.py:6: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
        from distutils.version import LooseVersion
    
    -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
    ================================================================================= short test summary info =================================================================================
    FAILED tests/test_areas/test_utils.py::TestGenerateAaliDict::test_aali_has_only_parent - StopIteration
    

    I would love try to do this with context managers, but I don't know how to get away with using them for two nested mocks per test like I'm using right now.

    question 
    opened by Lucasmiguelmac 3
  • spy on frozen dataclass

    spy on frozen dataclass

    Spy does not work on frozen dataclasses, it would be nice if it did (for instance, by using object.__setattr__(obj, name, spy)

    from dataclasses import dataclass
    from typing import Callable
    
    
    def noop(*args, **kwargs):
        pass
    
    
    @dataclass(frozen=True)
    class MyFrozenClass:
        something: Callable = noop
    
    
    def test_spy_frozen_dataclass(mocker: MockerFixture):
        o = MyFrozenClass()
        spy = mocker.spy(o, 'something')
    

    Anyone also in this situation can use this workaround:

    def test_spy_frozen_dataclass(mocker: MockerFixture):
        o = MyFrozenClass()
        spy = mocker.MagicMock(wraps=o.something)
        object.__setattr__(o, 'something', spy)
    
    enhancement 
    opened by jennydaman 1
  • Patch methods should return AsyncMock if the target is an async method

    Patch methods should return AsyncMock if the target is an async method

    This would match the behaviour of the equivalent methods in mock

    Currently, I can pass new_callable=AsyncMock to make it work, but then mypy type checking fails because the type hints state that the methods return MagicMock. The return type is a union in the mock stubs.

    help wanted 
    opened by GDYendell 1
  • Incorrect introspection for MagicMock.assert_has_calls

    Incorrect introspection for MagicMock.assert_has_calls

    Hi,

    I wrote a test that calls a MagicMock() with a list of bytes, then uses assert_has_calls with a different argument (list of strings).

    Here is pytest's output:

        def test_foo():
            from unittest.mock import MagicMock, call
        
            f = MagicMock()
        
            f("foo", [b"bar"])
            f("foo", [b"baz"])
        
            f.assert_has_calls(
                [
                    call("foo", ["bar"]),
                    call("foo", ["baz"]),
                ],
    >           any_order=True
            )
    E       AssertionError: (call('foo', ['bar']), call('foo', ['baz'])) not all found in call list
    E       
    E       pytest introspection follows:
    E       
    E       Args:
    E       assert ('foo', [b'baz']) == ([call('foo', ['bar']), call('foo', ['baz'])],)
    E         At index 0 diff: 'foo' != [call('foo', ['bar']), call('foo', ['baz'])]
    E         Left contains one more item: [b'baz']
    E         Full diff:
    E         - ([call('foo', ['bar']), call('foo', ['baz'])],)
    E         + ('foo', [b'baz'])
    E       Kwargs:
    E       assert {} == {'any_order': True}
    E         Right contains 1 more item:
    E         {'any_order': True}
    E         Full diff:
    E         - {'any_order': True}
    E         + {}
    

    The first line of the error(AssertionError) is correct, but the other ones aren't:

    • ('foo', [b'baz']) == ([call('foo', ['bar']), call('foo', ['baz'])],) is not exactly what was asserted; instead the assertion was that the left side is inside the right side's first element
    • assert {} == {'any_order': True} this is not part of the assertion, any_order is just an argument of the function

    Instead, I would probably expect something like this:

    E       AssertionError: (call('foo', ['bar']), call('foo', ['baz'])) not all found in call list
    E       
    E       pytest introspection follows:
    E       
    E       assert call('foo', [b'baz']) in [call('foo', ['bar']), call('foo', ['baz'])]
    

    OS: Debian 10

    Python version: 3.7.3

    pytest version: 6.2.2

    pip list
    Package                       Version                         Location
    ----------------------------- ------------------------------- ---------------------------------------------------------------------------
    aiohttp                       3.5.1
    aiohttp-utils                 3.1.1
    aiosqlite                     0.16.0
    alabaster                     0.7.12
    amqp                          2.5.2
    ansible                       2.7.7
    anyjson                       0.3.3
    apache-libcloud               2.4.0
    apipkg                        1.5
    appdirs                       1.4.3
    argcomplete                   1.8.1
    arrow                         0.12.1
    asgiref                       3.2.10
    asn1crypto                    0.24.0
    aspy.yaml                     1.3.0
    async-generator               1.10
    async-timeout                 3.0.1
    atomicwrites                  1.1.5
    attrs                         19.3.0
    attrs-strict                  0.1.0
    azure-common                  1.1.24
    azure-nspkg                   3.0.2
    azure-storage                 0.36.0
    Babel                         2.7.0
    bcrypt                        3.1.6
    beautifulsoup4                4.8.1
    billiard                      3.6.3.0
    binwalk                       2.1.2
    black                         19.10b0
    bleach                        3.1.2
    blessed                       1.15.0
    blinker                       1.4
    borgbackup                    1.1.9
    Brlapi                        0.6.7
    Brotli                        1.0.7
    cached-property               1.5.2
    cachetools                    4.2.0
    cassandra-driver              3.20.1
    celery                        4.4.0
    certifi                       2018.8.24
    cffi                          1.14.3
    cfgv                          2.0.1
    chardet                       3.0.4
    click                         7.1.2
    colorama                      0.3.7
    commonmark                    0.9.1
    confluent-kafka               1.5.0
    coreapi                       2.3.3
    coreschema                    0.0.4
    coverage                      5.0
    cryptography                  2.6.1
    cupshelpers                   1.0
    cycler                        0.10.0
    daiquiri                      2.1.1
    dash                          1.12.0
    dash-bootstrap-components     0.10.2
    dash-core-components          1.10.0
    dash-html-components          1.0.3
    dash-renderer                 1.4.1
    dash-table                    4.7.0
    decorator                     4.3.0
    defusedxml                    0.5.0
    Deprecated                    1.2.6
    devscripts                    2.19.5+deb10u1
    diffoscope                    113
    distro                        1.5.0
    distro-info                   0.21
    Django                        2.2.15
    django-cors-headers           3.2.0
    django-extensions             2.2.5
    django-js-reverse             0.9.1
    django-stubs                  1.7.0
    django-test-migrations        1.1.0
    django-webpack-loader         0.6.0
    djangorestframework           3.10.3
    djangorestframework-stubs     1.4.0
    docker                        4.3.1
    docker-compose                1.27.4
    dockerpty                     0.4.1
    docopt                        0.6.2
    docutils                      0.15.2
    dulwich                       0.19.13
    ecdsa                         0.15
    EditorConfig                  0.12.1
    elasticsearch                 7.0.5
    elementpath                   2.0.4
    enjarify                      1.0.3
    entrypoints                   0.3
    ephem                         3.7.6.0
    execnet                       1.7.1
    extras                        1.0.0
    fastimport                    0.9.8
    feedparser                    5.2.1
    filelock                      3.0.10
    fixtures                      3.0.0
    flake8                        3.8.3
    Flask                         1.1.1
    Flask-Compress                1.5.0
    fossology                     0.2.0
    frozendict                    1.2
    future                        0.18.2
    gbp                           0.9.14
    geomet                        0.1.2
    glob2                         0.7
    gpg                           1.12.0
    gunicorn                      19.9.0
    html5lib                      1.0.1
    htmlmin                       0.1.12
    httplib2                      0.11.3
    humanize                      3.2.0
    hypothesis                    5.49.0
    identify                      1.4.7
    idna                          2.6
    imagesize                     1.1.0
    importlib-metadata            0.23
    iniconfig                     1.0.1
    iotop                         0.6
    ipykernel                     4.9.0
    ipython                       5.8.0
    ipython-genutils              0.2.0
    ipywidgets                    6.0.0
    iso8601                       0.1.12
    isodate                       0.6.0
    isort                         5.5.3
    itsdangerous                  0.24
    itypes                        1.2.0
    Jinja2                        2.10.3
    jmespath                      0.9.4
    jsbeautifier                  1.6.4
    jsondiff                      1.1.1
    jsonschema                    2.6.0
    junit-xml                     1.8
    jupyter-client                5.2.3
    jupyter-core                  4.4.0
    kafka-python                  2.0.0
    keyring                       17.1.1
    keyrings.alt                  3.1.1
    kiwisolver                    1.0.1
    kombu                         4.6.7
    launchpadlib                  1.10.13
    lazr.restfulclient            0.14.3
    lazr.uri                      1.0.3
    libarchive-c                  2.8
    linecache2                    1.0.0
    llfuse                        1.3.6
    lockfile                      0.12.2
    louis                         3.8.0
    lxml                          4.4.1
    markdown-it-py                0.5.6
    MarkupSafe                    1.1.0
    matplotlib                    3.0.2
    mccabe                        0.6.1
    mercurial                     5.7
    meson                         0.49.2
    mirakuru                      2.3.0
    mistune                       0.8.4
    more-itertools                4.2.0
    msgpack                       1.0.0
    multidict                     4.5.2
    musicbrainzngs                0.6
    mutagen                       1.40.0
    mutmut                        2.0.0
    mypy                          0.800
    mypy-extensions               0.4.3
    myst-parser                   0.12.10
    nagiosplugin                  1.3.2
    nbconvert                     5.4.0
    nbformat                      4.4.0
    ndjson                        0.3.1
    netaddr                       0.7.19
    nodeenv                       1.3.3
    nose                          1.3.7
    notebook                      5.7.8
    ntlm-auth                     1.1.0
    numexpr                       2.6.9
    numpy                         1.16.2
    oauthlib                      3.1.0
    olefile                       0.46
    outcome                       1.1.0
    packaging                     19.2
    pandas                        0.23.3+dfsg
    pandocfilters                 1.4.2
    paramiko                      2.4.2
    parso                         0.7.0
    pathspec                      0.7.0
    patool                        1.12
    pbr                           5.4.5
    pexpect                       4.6.0
    pg-activity                   2.1.0
    pg8000                        1.13.2
    pickleshare                   0.7.5
    pifpaf                        3.0.0
    pika                          1.1.0
    Pillow                        5.4.1
    pip                           21.0.1
    pkginfo                       1.5.0.1
    plotille                      3.7.2
    plotly                        4.5.4
    pluggy                        0.13.1
    pony                          0.7.13
    port-for                      0.4
    powerline-status              2.7
    pre-commit                    1.20.0
    pristine-zip                  0.1.dev73+gefd1d06.d20200805    /home/dev/pristine_zip
    progressbar                   2.5
    prometheus-client             0.6.0
    prompt-toolkit                1.0.15
    psutil                        5.5.1
    psycopg2                      2.8.6
    py                            1.9.0
    py4j                          0.10.8.1
    pyasn1                        0.4.2
    pybadges                      2.2.1
    pybloomfiltermmap3            0.5.3
    pycairo                       1.16.2
    pycodestyle                   2.6.0
    pycparser                     2.20
    pycrypto                      2.6.1
    pycups                        1.9.73
    pycurl                        7.43.0.2
    pyflakes                      2.2.0
    pyfuse3                       3.1.1
    Pygments                      2.3.1
    PyGObject                     3.30.4
    pyinotify                     0.9.6
    pykerberos                    1.1.14
    PyLD                          2.0.3
    PyNaCl                        1.3.0
    PyOpenGL                      3.1.0
    pyOpenSSL                     19.0.0
    pypandoc                      1.4
    pyparsing                     2.2.0
    PyPDF2                        1.26.0
    pyqtgraph                     0.10.0
    PySimpleSOAP                  1.16.2
    pysmbc                        1.0.15.6
    pytest                        6.2.2
    pytest-cov                    2.10.0
    pytest-cover                  3.0.0
    pytest-coverage               0.0
    pytest-django                 3.7.0
    pytest-forked                 1.1.3
    pytest-kafka                  0.4.0
    pytest-mock                   1.13.0
    pytest-parallel               0.0.10
    pytest-postgresql             2.5.3
    pytest-xdist                  1.31.0
    python-apt                    1.8.4.3
    python-cephlibs               0.94.5.post1
    python-daemon                 2.2.4
    python-dateutil               2.8.1
    python-debian                 0.1.35
    python-debianbts              2.8.2
    python-dotenv                 0.15.0
    python-hglib                  2.6.1
    python-jose                   3.1.0
    python-json-logger            0.1.11
    python-keycloak               0.20.0
    python-magic                  0.4.16
    python-memcached              1.58
    python-mimeparse              1.6.0
    pytz                          2019.1
    pywinrm                       0.3.0
    pyxattr                       0.6.1
    pyxdg                         0.25
    PyYAML                        3.13
    pyzmq                         17.1.2
    quodlibet                     4.2.1
    rados                         2.0.0
    rdflib                        5.0.0
    rdflib-jsonld                 0.5.0
    recommonmark                  0.6.0
    redis                         3.3.11
    regex                         2020.2.20
    reportbug                     7.5.3-deb10u1
    reportlab                     3.5.13
    requests                      2.25.1
    requests-ftp                  0.3.1
    requests-kerberos             0.11.0
    requests-mock                 1.8.0
    requests-ntlm                 1.1.0
    retrying                      1.3.3
    rsa                           4.0
    scipy                         1.1.0
    scour                         0.37
    scramp                        1.1.0
    SecretStorage                 2.3.1
    Send2Trash                    1.5.0
    sentry-sdk                    0.13.5
    setuptools                    40.8.0
    simplegeneric                 0.8.1
    simplejson                    3.16.0
    simpy                         3.0.13
    six                           1.12.0
    sniffio                       1.2.0
    snowballstemmer               2.0.0
    sortedcontainers              2.1.0
    soupsieve                     1.9.5
    Sphinx                        3.3.1
    sphinx-click                  2.5.0
    sphinx-rtd-theme              0.5.0
    sphinx-tabs                   1.3.0
    sphinxcontrib-applehelp       1.0.1
    sphinxcontrib-devhelp         1.0.1
    sphinxcontrib-htmlhelp        1.0.2
    sphinxcontrib-httpdomain      1.7.0
    sphinxcontrib-images          0.9.2
    sphinxcontrib-jsmath          1.0.1
    sphinxcontrib-programoutput   0.16
    sphinxcontrib-qthelp          1.0.2
    sphinxcontrib-serializinghtml 1.1.3
    SQLAlchemy                    1.3.10
    sqlalchemy-stubs              0.2
    sqlitedict                    1.6.0
    sqlparse                      0.3.1
    subvertpy                     0.10.1
    swh.clearlydefined            0.1.dev5+g430c67f               /home/dev/swh-environment/swh-clearlydefined
    swh.core                      0.12.0                          /home/dev/.local/lib/python3.7/site-packages
    swh.deposit                   0.6.1.dev24+g22172d4e           /home/dev/swh-environment/swh-deposit
    swh.docs                      0.0.1.dev287+g54fe755.d20210325 /home/dev/swh-environment/swh-docs
    swh.fuse                      0.9.2                           /home/dev/.local/lib/python3.7/site-packages
    swh.graph                     0.2.10.dev45+g5a987aa           /home/dev/swh-environment/swh-graph
    swh.icinga-plugins            0.2.2.dev1+g441faf2             /home/dev/swh-environment/swh-icinga-plugins
    swh.indexer                   0.6.4.dev4+g3baf8bb             /home/dev/swh-environment/swh-indexer
    swh.journal                   0.7.2.dev3+g458a405.d20210322   /home/dev/swh-environment/swh-journal
    swh.lister                    0.4.1.dev9+gc782275             /home/dev/swh-environment/swh-lister
    swh.loader.core               0.20.1.dev4+gcf8fc9e            /home/dev/swh-environment/swh-loader-core
    swh.loader.git                0.3.6                           /home/dev/swh-environment/swh-loader-git
    swh.loader.mercurial          0.4.0                           /home/dev/swh-environment/swh-loader-mercurial
    swh.loader.svn                0.0.54.post2                    /home/dev/swh-environment/swh-loader-svn
    swh.mirror.forge              0.0.5.post20                    /home/dev/swh-environment/swh-mirror-forge
    swh.model                     2.3.0                           /home/dev/.local/lib/python3.7/site-packages/swh.model-2.3.0-py3.7.egg
    swh.objstorage                0.2.2                           /home/dev/.local/lib/python3.7/site-packages/swh.objstorage-0.2.2-py3.7.egg
    swh.objstorage.replayer       0.2.1                           /home/dev/swh-environment/swh-objstorage-replayer
    swh.scanner                   0.3.1.dev0+g33a9cd4.d20210301   /home/dev/swh-environment/swh-scanner
    swh.scheduler                 0.10.0                          /home/dev/.local/lib/python3.7/site-packages
    swh.search                    0.3.3.dev1+g4390bea.d20201211   /home/dev/swh-environment/swh-search
    swh.storage                   0.26.0                          /home/dev/swh-environment/swh-storage
    swh.vault                     0.0.35.dev3+gd64687d.d20200904  /home/dev/swh-environment/swh-vault
    swh.web                       0.0.284.dev6+g0b974c89          /home/dev/swh-environment/swh-web
    swh.web.client                0.2.2                           /home/dev/.local/lib/python3.7/site-packages
    systemd-python                234
    tables                        3.4.4
    tblib                         1.6.0
    tenacity                      6.0.0
    terminado                     0.8.1
    testinfra                     4.0.0
    testing.common.database       2.0.3
    testing.postgresql            1.3.0
    testpath                      0.4.2
    testresources                 2.0.1
    testtools                     2.4.0
    texttable                     1.6.3
    tlsh                          0.2.0
    toml                          0.10.2
    tornado                       5.1.1
    tox                           3.7.0
    traceback2                    1.4.0
    traitlets                     4.3.2
    trio                          0.17.0
    typed-ast                     1.4.0
    typing-extensions             3.7.4.1
    unattended-upgrades           0.1
    unidiff                       0.5.4
    unittest2                     1.1.0
    uritemplate                   3.0.1
    urllib3                       1.24.1
    vcversioner                   2.16.0.0
    vine                          1.3.0
    virtualenv                    16.7.7
    wadllib                       1.3.4
    wcwidth                       0.1.7
    webencodings                  0.5.1
    websocket-client              0.57.0
    Werkzeug                      0.16.0
    wheel                         0.32.3
    widgetsnbextension            2.0.0
    wrapt                         1.11.2
    xattr                         0.9.7
    xmlschema                     1.3.1
    xmltodict                     0.11.0
    yarl                          1.3.0
    zipp                          0.6.0
    

    Thanks!

    opened by progval 3
  • Allow use of custom mock implementations

    Allow use of custom mock implementations

    With the growing use of asyncio, we need ways to mock Coroutines.

    Currently, mock and unittest.mock do not support creating specs for coroutines (AsyncMock is being added in python 3.8).

    As a work around, we're using asynctest.mock, which has the same interface as unittest.mock, however this requires us to completely re-implement the __init__ method of MockFixture, and removes the "hide traceback" functionality (though we don't care too much about this). This allows us to have both mocker and async_mocker fixtures.

    TLDR To ease this usecase (and potentially others), Can support for defining a mock modules path from the config be added please?

    opened by antdking 7
  • Drop RuntimeError handling when we only support Python 3.8+

    Drop RuntimeError handling when we only support Python 3.8+

    Just to add to this the RuntimeError was removed in CPython and mock 3.0.0 due to similar concerns raised in #137 . Upstream issue : https://bugs.python.org/issue36366 .

    Originally posted by @tirkarthi in https://github.com/pytest-dev/pytest-mock/pull/138#issuecomment-490138801

    opened by nicoddemus 0
Releases(v3.10.0)
  • v3.10.0(Oct 5, 2022)

  • v3.9.0(Sep 28, 2022)

  • v3.8.2(Jul 5, 2022)

  • v3.8.1(Jun 24, 2022)

  • v3.8.0(Jun 24, 2022)

  • v3.7.0(Jan 28, 2022)

  • v3.6.1(May 18, 2021)

  • v3.6.0(May 18, 2021)

  • v3.5.1(May 18, 2021)

  • v3.5.0(May 18, 2021)

    • Now all patch functions will emit a warning instead of raising a ValueError when used as a context-manager. Thanks @iforapsy for the PR (#221).
    • Additionally, mocker.patch.context_manager is available when the user intends to mock a context manager (for example threading.Lock object), which will not emit that warning.
    Source code(tar.gz)
    Source code(zip)
  • v3.4.0(May 18, 2021)

    • Add [mock.seal]{.title-ref} alias to the [mocker]{.title-ref} fixture (#211). Thanks @coiax for the PR.

    • Fixed spying on exceptions not covered by the Exception superclass (#215), like KeyboardInterrupt -- PR #216 by @webknjaz.

      Before the fix, both spy_return and spy_exception were always assigned to None whenever such an exception happened. And after this fix, spy_exception is set to a correct value of an exception

    Source code(tar.gz)
    Source code(zip)
  • v3.3.1(Aug 26, 2020)

    • Introduce MockFixture as an alias to MockerFixture.

      Before 3.3.0, the fixture class was named MockFixture, but was renamed to MockerFixture to better match the mocker fixture. While not officially part of the API, it was later discovered that this broke the code of some users which already imported pytest_mock.MockFixture for type annotations, so we decided to reintroduce the name as an alias.

      Note however that this is just a stop gap measure, and new code should use MockerFixture for type annotations.

    • Improved typing for MockerFixture.patch (#201). Thanks @srittau for the PR.

    Source code(tar.gz)
    Source code(zip)
  • v3.3.0(Aug 22, 2020)

    • pytest-mock now includes inline type annotations and exposes them to user programs. The mocker fixture returns pytest_mock.MockerFixture, which can be used to annotate your tests:

      from pytest_mock import MockerFixture
      
      def test_foo(mocker: MockerFixture) -> None:
          ...
      

      The type annotations were developed against mypy version 0.782, the minimum version supported at the moment. If you run into an error that you believe to be incorrect, please open an issue.

      Many thanks to @staticdev for providing the initial patch #199.

    Source code(tar.gz)
    Source code(zip)
  • v3.2.0(Jul 11, 2020)

  • v3.1.1(Jun 5, 2020)

  • v3.1.0(May 15, 2020)

  • v3.0.0(Mar 31, 2020)

    • Python 2.7 and 3.4 are no longer supported. Users using pip 9 or later will install a compatible version automatically.
    • mocker.spy now also works with async def functions (#179). Thanks @frankie567 for the PR!
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jan 4, 2020)

    Breaking Changes

    • mocker.spy attributes for tracking returned values and raised exceptions of its spied functions are now called spy_return and spy_exception, instead of reusing the existing MagicMock attributes return_value and side_effect.

      Version 1.13 introduced a serious regression: after a spied function using mocker.spy raises an exception, further calls to the spy will not call the spied function, always raising the first exception instead: assigning to side_effect causes unittest.mock to behave this way (#175).

    • The deprecated mock alias to the mocker fixture has finally been removed.

    Source code(tar.gz)
    Source code(zip)
  • v1.13.0(Dec 6, 2019)

  • v1.12.1(Nov 22, 2019)

  • v1.12.0(Nov 19, 2019)

  • v1.11.2(Oct 24, 2019)

    • The pytest introspection follows message is no longer shown if there is no pytest introspection (#154). Thanks @The-Compiler for the report.

    • mocker now raises a ValueError when used as a context-manager. Thanks @binarymason for the PR (#165).

    Source code(tar.gz)
    Source code(zip)
  • v1.11.1(Oct 11, 2019)

  • v1.11.0(Oct 4, 2019)

  • v0.8.1(Sep 29, 2015)

    • mock.ANY is now accessible from the mocker fixture (#17), thanks @tigarmo for the PR!
    • pytest-mock is now also available as a wheel. Thanks @rouge8 for the PR!
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Jul 7, 2015)

  • v0.6.0(Jun 2, 2015)

  • v0.5.0(May 3, 2015)

  • v0.4.3(Apr 9, 2015)

  • v0.4.2(Mar 31, 2015)

    Small fix, no longer using wheel as an alternate package since it conditionally depends on mock module based on Python version, as Python >= 3.3 already includes unittest.mock . Many thanks to @The-Compiler for letting me know and providing a PR with the fix!

    Source code(tar.gz)
    Source code(zip)
Owner
pytest-dev
pytest-dev
ApiPy was created for api testing with Python pytest framework which has also requests, assertpy and pytest-html-reporter libraries.

ApiPy was created for api testing with Python pytest framework which has also requests, assertpy and pytest-html-reporter libraries. With this f

Mustafa 1 Jul 11, 2022
Playwright Python tool practice pytest pytest-bdd screen-play page-object allure cucumber-report

pytest-ui-automatic Playwright Python tool practice pytest pytest-bdd screen-play page-object allure cucumber-report How to run Run tests execute_test

moyu6027 11 Nov 8, 2022
pytest plugin providing a function to check if pytest is running.

pytest-is-running pytest plugin providing a function to check if pytest is running. Installation Install with: python -m pip install pytest-is-running

Adam Johnson 21 Nov 1, 2022
Pytest-typechecker - Pytest plugin to test how type checkers respond to code

pytest-typechecker this is a plugin for pytest that allows you to create tests t

vivax 2 Aug 20, 2022
Pytest-rich - Pytest + rich integration (proof of concept)

pytest-rich Leverage rich for richer test session output. This plugin is not pub

Bruno Oliveira 170 Dec 2, 2022
A pytest plugin to run an ansible collection's unit tests with pytest.

pytest-ansible-units An experimental pytest plugin to run an ansible collection's unit tests with pytest. Description pytest-ansible-units is a pytest

Community managed Ansible repositories 9 Dec 9, 2022
Aioresponses is a helper for mock/fake web requests in python aiohttp package.

aioresponses Aioresponses is a helper to mock/fake web requests in python aiohttp package. For requests module there are a lot of packages that help u

null 402 Jan 6, 2023
It helps to use fixtures in pytest.mark.parametrize

pytest-lazy-fixture Use your fixtures in @pytest.mark.parametrize. Installation pip install pytest-lazy-fixture Usage import pytest @pytest.fixture(p

Marsel Zaripov 299 Dec 24, 2022
Minimal example of how to use pytest with automated 'devops' style automated test runs

Pytest python example with automated testing This is a minimal viable example of pytest with an automated run of tests for every push/merge into the m

Karma Computing 2 Jan 2, 2022
PyAutoEasy is a extension / wrapper around the famous PyAutoGUI, a cross-platform GUI automation tool to replace your boooring repetitive tasks.

PyAutoEasy PyAutoEasy is a extension / wrapper around the famous PyAutoGUI, a cross-platform GUI automation tool to replace your boooring repetitive t

Dingu Sagar 7 Oct 27, 2022
a socket mock framework - for all kinds of socket animals, web-clients included

mocket /mɔˈkɛt/ A socket mock framework for all kinds of socket animals, web-clients included - with gevent/asyncio/SSL support ...and then MicroPytho

Giorgio Salluzzo 249 Dec 14, 2022
Automatically mock your HTTP interactions to simplify and speed up testing

VCR.py ?? This is a Python version of Ruby's VCR library. Source code https://github.com/kevin1024/vcrpy Documentation https://vcrpy.readthedocs.io/ R

Kevin McCarthy 2.3k Jan 1, 2023
Automatically mock your HTTP interactions to simplify and speed up testing

VCR.py ?? This is a Python version of Ruby's VCR library. Source code https://github.com/kevin1024/vcrpy Documentation https://vcrpy.readthedocs.io/ R

Kevin McCarthy 1.8k Feb 7, 2021
a socket mock framework - for all kinds of socket animals, web-clients included

mocket /mɔˈkɛt/ A socket mock framework for all kinds of socket animals, web-clients included - with gevent/asyncio/SSL support ...and then MicroPytho

Giorgio Salluzzo 208 Jan 31, 2021
Mockoon is the easiest and quickest way to run mock APIs locally. No remote deployment, no account required, open source.

Mockoon Mockoon is the easiest and quickest way to run mock APIs locally. No remote deployment, no account required, open source. It has been built wi

mockoon 4.4k Dec 30, 2022
Cornell record & replay mock server

Cornell: record & replay mock server Cornell makes it dead simple, via its record and replay features to perform end-to-end testing in a fast and isol

HiredScoreLabs 134 Sep 15, 2022
Mock smart contracts for writing Ethereum test suites

Mock smart contracts for writing Ethereum test suites This package contains comm

Trading Strategy 222 Jan 4, 2023
User-interest mock backend server implemnted using flask restful, and SQLAlchemy ORM confiugred with sqlite

Flask_Restful_SQLAlchemy_server User-interest mock backend server implemnted using flask restful, and SQLAlchemy ORM confiugred with sqlite. Backend b

Austin Weigel 1 Nov 17, 2022
A Django plugin for pytest.

Welcome to pytest-django! pytest-django allows you to test your Django project/applications with the pytest testing tool. Quick start / tutorial Chang

pytest-dev 1.1k Dec 31, 2022