
:mod:`unittest.mock` --- mock object library
============================================

.. module:: unittest.mock
   :synopsis: Mock object library.
.. moduleauthor:: Michael Foord <michael@python.org>
.. currentmodule:: unittest.mock

.. versionadded:: 3.3

:mod:`unittest.mock` is a library for testing in Python. It allows you to
replace parts of your system under test with mock objects and make assertions
about how they have been used.

`unittest.mock` provides a core :class:`Mock` class removing the need to
create a host of stubs throughout your test suite. After performing an
action, you can make assertions about which methods / attributes were used
and arguments they were called with. You can also specify return values and
set needed attributes in the normal way.

Additionally, mock provides a :func:`patch` decorator that handles patching
module and class level attributes within the scope of a test, along with
:const:`sentinel` for creating unique objects. See the `quick guide`_ for
some examples of how to use :class:`Mock`, :class:`MagicMock` and
:func:`patch`.

Mock is very easy to use and is designed for use with :mod:`unittest`. Mock
is based on the 'action -> assertion' pattern instead of `'record -> replay'`
used by many mocking frameworks.

There is a backport of `unittest.mock` for earlier versions of Python,
available as `mock on PyPI <http://pypi.python.org/pypi/mock>`_.

**Source code:** :source:`Lib/unittest/mock.py`


Quick Guide
-----------

:class:`Mock` and :class:`MagicMock` objects create all attributes and
methods as you access them and store details of how they have been used. You
can configure them, to specify return values or limit what attributes are
available, and then make assertions about how they have been used:

    >>> from unittest.mock import MagicMock
    >>> thing = ProductionClass()
    >>> thing.method = MagicMock(return_value=3)
    >>> thing.method(3, 4, 5, key='value')
    3
    >>> thing.method.assert_called_with(3, 4, 5, key='value')

:attr:`side_effect` allows you to perform side effects, including raising an
exception when a mock is called:

   >>> mock = Mock(side_effect=KeyError('foo'))
   >>> mock()
   Traceback (most recent call last):
    ...
   KeyError: 'foo'

   >>> values = {'a': 1, 'b': 2, 'c': 3}
   >>> def side_effect(arg):
   ...     return values[arg]
   ...
   >>> mock.side_effect = side_effect
   >>> mock('a'), mock('b'), mock('c')
   (1, 2, 3)
   >>> mock.side_effect = [5, 4, 3, 2, 1]
   >>> mock(), mock(), mock()
   (5, 4, 3)

Mock has many other ways you can configure it and control its behaviour. For
example the `spec` argument configures the mock to take its specification
from another object. Attempting to access attributes or methods on the mock
that don't exist on the spec will fail with an `AttributeError`.

The :func:`patch` decorator / context manager makes it easy to mock classes or
objects in a module under test. The object you specify will be replaced with a
mock (or other object) during the test and restored when the test ends:

    >>> from unittest.mock import patch
    >>> @patch('module.ClassName2')
    ... @patch('module.ClassName1')
    ... def test(MockClass1, MockClass2):
    ...     module.ClassName1()
    ...     module.ClassName2()
    ...     assert MockClass1 is module.ClassName1
    ...     assert MockClass2 is module.ClassName2
    ...     assert MockClass1.called
    ...     assert MockClass2.called
    ...
    >>> test()

.. note::

   When you nest patch decorators the mocks are passed in to the decorated
   function in the same order they applied (the normal *python* order that
   decorators are applied). This means from the bottom up, so in the example
   above the mock for `module.ClassName1` is passed in first.

   With `patch` it matters that you patch objects in the namespace where they
   are looked up. This is normally straightforward, but for a quick guide
   read :ref:`where to patch <where-to-patch>`.

As well as a decorator `patch` can be used as a context manager in a with
statement:

    >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
    ...     thing = ProductionClass()
    ...     thing.method(1, 2, 3)
    ...
    >>> mock_method.assert_called_once_with(1, 2, 3)


There is also :func:`patch.dict` for setting values in a dictionary just
during a scope and restoring the dictionary to its original state when the test
ends:

   >>> foo = {'key': 'value'}
   >>> original = foo.copy()
   >>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):
   ...     assert foo == {'newkey': 'newvalue'}
   ...
   >>> assert foo == original

Mock supports the mocking of Python :ref:`magic methods <magic-methods>`. The
easiest way of using magic methods is with the :class:`MagicMock` class. It
allows you to do things like:

    >>> mock = MagicMock()
    >>> mock.__str__.return_value = 'foobarbaz'
    >>> str(mock)
    'foobarbaz'
    >>> mock.__str__.assert_called_with()

Mock allows you to assign functions (or other Mock instances) to magic methods
and they will be called appropriately. The `MagicMock` class is just a Mock
variant that has all of the magic methods pre-created for you (well, all the
useful ones anyway).

The following is an example of using magic methods with the ordinary Mock
class:

    >>> mock = Mock()
    >>> mock.__str__ = Mock(return_value='wheeeeee')
    >>> str(mock)
    'wheeeeee'

For ensuring that the mock objects in your tests have the same api as the
objects they are replacing, you can use :ref:`auto-speccing <auto-speccing>`.
Auto-speccing can be done through the `autospec` argument to patch, or the
:func:`create_autospec` function. Auto-speccing creates mock objects that
have the same attributes and methods as the objects they are replacing, and
any functions and methods (including constructors) have the same call
signature as the real object.

This ensures that your mocks will fail in the same way as your production
code if they are used incorrectly:

   >>> from unittest.mock import create_autospec
   >>> def function(a, b, c):
   ...     pass
   ...
   >>> mock_function = create_autospec(function, return_value='fishy')
   >>> mock_function(1, 2, 3)
   'fishy'
   >>> mock_function.assert_called_once_with(1, 2, 3)
   >>> mock_function('wrong arguments')
   Traceback (most recent call last):
    ...
   TypeError: <lambda>() takes exactly 3 arguments (1 given)

`create_autospec` can also be used on classes, where it copies the signature of
the `__init__` method, and on callable objects where it copies the signature of
the `__call__` method.



The Mock Class
--------------


`Mock` is a flexible mock object intended to replace the use of stubs and
test doubles throughout your code. Mocks are callable and create attributes as
new mocks when you access them [#]_. Accessing the same attribute will always
return the same mock. Mocks record how you use them, allowing you to make
assertions about what your code has done to them.

:class:`MagicMock` is a subclass of `Mock` with all the magic methods
pre-created and ready to use. There are also non-callable variants, useful
when you are mocking out objects that aren't callable:
:class:`NonCallableMock` and :class:`NonCallableMagicMock`

The :func:`patch` decorators makes it easy to temporarily replace classes
in a particular module with a `Mock` object. By default `patch` will create
a `MagicMock` for you. You can specify an alternative class of `Mock` using
the `new_callable` argument to `patch`.


.. class:: Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, **kwargs)

    Create a new `Mock` object. `Mock` takes several optional arguments
    that specify the behaviour of the Mock object:

    * `spec`: This can be either a list of strings or an existing object (a
      class or instance) that acts as the specification for the mock object. If
      you pass in an object then a list of strings is formed by calling dir on
      the object (excluding unsupported magic attributes and methods).
      Accessing any attribute not in this list will raise an `AttributeError`.

      If `spec` is an object (rather than a list of strings) then
      :attr:`__class__` returns the class of the spec object. This allows mocks
      to pass `isinstance` tests.

    * `spec_set`: A stricter variant of `spec`. If used, attempting to *set*
      or get an attribute on the mock that isn't on the object passed as
      `spec_set` will raise an `AttributeError`.

    * `side_effect`: A function to be called whenever the Mock is called. See
      the :attr:`~Mock.side_effect` attribute. Useful for raising exceptions or
      dynamically changing return values. The function is called with the same
      arguments as the mock, and unless it returns :data:`DEFAULT`, the return
      value of this function is used as the return value.

      Alternatively `side_effect` can be an exception class or instance. In
      this case the exception will be raised when the mock is called.

      If `side_effect` is an iterable then each call to the mock will return
      the next value from the iterable.

      A `side_effect` can be cleared by setting it to `None`.

    * `return_value`: The value returned when the mock is called. By default
      this is a new Mock (created on first access). See the
      :attr:`return_value` attribute.

    * `wraps`: Item for the mock object to wrap. If `wraps` is not None then
      calling the Mock will pass the call through to the wrapped object
      (returning the real result). Attribute access on the mock will return a
      Mock object that wraps the corresponding attribute of the wrapped
      object (so attempting to access an attribute that doesn't exist will
      raise an `AttributeError`).

      If the mock has an explicit `return_value` set then calls are not passed
      to the wrapped object and the `return_value` is returned instead.

    * `name`: If the mock has a name then it will be used in the repr of the
      mock. This can be useful for debugging. The name is propagated to child
      mocks.

    Mocks can also be called with arbitrary keyword arguments. These will be
    used to set attributes on the mock after it is created. See the
    :meth:`configure_mock` method for details.


    .. method:: assert_called_with(*args, **kwargs)

        This method is a convenient way of asserting that calls are made in a
        particular way:

            >>> mock = Mock()
            >>> mock.method(1, 2, 3, test='wow')
            <Mock name='mock.method()' id='...'>
            >>> mock.method.assert_called_with(1, 2, 3, test='wow')

    .. method:: assert_called_once_with(*args, **kwargs)

       Assert that the mock was called exactly once and with the specified
       arguments.

            >>> mock = Mock(return_value=None)
            >>> mock('foo', bar='baz')
            >>> mock.assert_called_once_with('foo', bar='baz')
            >>> mock('foo', bar='baz')
            >>> mock.assert_called_once_with('foo', bar='baz')
            Traceback (most recent call last):
              ...
            AssertionError: Expected 'mock' to be called once. Called 2 times.


    .. method:: assert_any_call(*args, **kwargs)

        assert the mock has been called with the specified arguments.

        The assert passes if the mock has *ever* been called, unlike
        :meth:`assert_called_with` and :meth:`assert_called_once_with` that
        only pass if the call is the most recent one.

            >>> mock = Mock(return_value=None)
            >>> mock(1, 2, arg='thing')
            >>> mock('some', 'thing', 'else')
            >>> mock.assert_any_call(1, 2, arg='thing')


    .. method:: assert_has_calls(calls, any_order=False)

        assert the mock has been called with the specified calls.
        The `mock_calls` list is checked for the calls.

        If `any_order` is False (the default) then the calls must be
        sequential. There can be extra calls before or after the
        specified calls.

        If `any_order` is True then the calls can be in any order, but
        they must all appear in :attr:`mock_calls`.

            >>> mock = Mock(return_value=None)
            >>> mock(1)
            >>> mock(2)
            >>> mock(3)
            >>> mock(4)
            >>> calls = [call(2), call(3)]
            >>> mock.assert_has_calls(calls)
            >>> calls = [call(4), call(2), call(3)]
            >>> mock.assert_has_calls(calls, any_order=True)


    .. method:: reset_mock()

        The reset_mock method resets all the call attributes on a mock object:

            >>> mock = Mock(return_value=None)
            >>> mock('hello')
            >>> mock.called
            True
            >>> mock.reset_mock()
            >>> mock.called
            False

        This can be useful where you want to make a series of assertions that
        reuse the same object. Note that `reset_mock` *doesn't* clear the
        return value, :attr:`side_effect` or any child attributes you have
        set using normal assignment. Child mocks and the return value mock
        (if any) are reset as well.


    .. method:: mock_add_spec(spec, spec_set=False)

        Add a spec to a mock. `spec` can either be an object or a
        list of strings. Only attributes on the `spec` can be fetched as
        attributes from the mock.

        If `spec_set` is `True` then only attributes on the spec can be set.


    .. method:: attach_mock(mock, attribute)

        Attach a mock as an attribute of this one, replacing its name and
        parent. Calls to the attached mock will be recorded in the
        :attr:`method_calls` and :attr:`mock_calls` attributes of this one.


    .. method:: configure_mock(**kwargs)

        Set attributes on the mock through keyword arguments.

        Attributes plus return values and side effects can be set on child
        mocks using standard dot notation and unpacking a dictionary in the
        method call:

            >>> mock = Mock()
            >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
            >>> mock.configure_mock(**attrs)
            >>> mock.method()
            3
            >>> mock.other()
            Traceback (most recent call last):
              ...
            KeyError

        The same thing can be achieved in the constructor call to mocks:

            >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
            >>> mock = Mock(some_attribute='eggs', **attrs)
            >>> mock.some_attribute
            'eggs'
            >>> mock.method()
            3
            >>> mock.other()
            Traceback (most recent call last):
              ...
            KeyError

        `configure_mock` exists to make it easier to do configuration
        after the mock has been created.


    .. method:: __dir__()

        `Mock` objects limit the results of `dir(some_mock)` to useful results.
        For mocks with a `spec` this includes all the permitted attributes
        for the mock.

        See :data:`FILTER_DIR` for what this filtering does, and how to
        switch it off.


    .. method:: _get_child_mock(**kw)

        Create the child mocks for attributes and return value.
        By default child mocks will be the same type as the parent.
        Subclasses of Mock may want to override this to customize the way
        child mocks are made.

        For non-callable mocks the callable variant will be used (rather than
        any custom subclass).


    .. attribute:: called

        A boolean representing whether or not the mock object has been called:

            >>> mock = Mock(return_value=None)
            >>> mock.called
            False
            >>> mock()
            >>> mock.called
            True

    .. attribute:: call_count

        An integer telling you how many times the mock object has been called:

            >>> mock = Mock(return_value=None)
            >>> mock.call_count
            0
            >>> mock()
            >>> mock()
            >>> mock.call_count
            2


    .. attribute:: return_value

        Set this to configure the value returned by calling the mock:

            >>> mock = Mock()
            >>> mock.return_value = 'fish'
            >>> mock()
            'fish'

        The default return value is a mock object and you can configure it in
        the normal way:

            >>> mock = Mock()
            >>> mock.return_value.attribute = sentinel.Attribute
            >>> mock.return_value()
            <Mock name='mock()()' id='...'>
            >>> mock.return_value.assert_called_with()

        `return_value` can also be set in the constructor:

            >>> mock = Mock(return_value=3)
            >>> mock.return_value
            3
            >>> mock()
            3


    .. attribute:: side_effect

        This can either be a function to be called when the mock is called,
        or an exception (class or instance) to be raised.

        If you pass in a function it will be called with same arguments as the
        mock and unless the function returns the :data:`DEFAULT` singleton the
        call to the mock will then return whatever the function returns. If the
        function returns :data:`DEFAULT` then the mock will return its normal
        value (from the :attr:`return_value`).

        An example of a mock that raises an exception (to test exception
        handling of an API):

            >>> mock = Mock()
            >>> mock.side_effect = Exception('Boom!')
            >>> mock()
            Traceback (most recent call last):
              ...
            Exception: Boom!

        Using `side_effect` to return a sequence of values:

            >>> mock = Mock()
            >>> mock.side_effect = [3, 2, 1]
            >>> mock(), mock(), mock()
            (3, 2, 1)

        The `side_effect` function is called with the same arguments as the
        mock (so it is wise for it to take arbitrary args and keyword
        arguments) and whatever it returns is used as the return value for
        the call. The exception is if `side_effect` returns :data:`DEFAULT`,
        in which case the normal :attr:`return_value` is used.

            >>> mock = Mock(return_value=3)
            >>> def side_effect(*args, **kwargs):
            ...     return DEFAULT
            ...
            >>> mock.side_effect = side_effect
            >>> mock()
            3

        `side_effect` can be set in the constructor. Here's an example that
        adds one to the value the mock is called with and returns it:

            >>> side_effect = lambda value: value + 1
            >>> mock = Mock(side_effect=side_effect)
            >>> mock(3)
            4
            >>> mock(-8)
            -7

        Setting `side_effect` to `None` clears it:

            >>> m = Mock(side_effect=KeyError, return_value=3)
            >>> m()
            Traceback (most recent call last):
             ...
            KeyError
            >>> m.side_effect = None
            >>> m()
            3


    .. attribute:: call_args

        This is either `None` (if the mock hasn't been called), or the
        arguments that the mock was last called with. This will be in the
        form of a tuple: the first member is any ordered arguments the mock
        was called with (or an empty tuple) and the second member is any
        keyword arguments (or an empty dictionary).

            >>> mock = Mock(return_value=None)
            >>> print mock.call_args
            None
            >>> mock()
            >>> mock.call_args
            call()
            >>> mock.call_args == ()
            True
            >>> mock(3, 4)
            >>> mock.call_args
            call(3, 4)
            >>> mock.call_args == ((3, 4),)
            True
            >>> mock(3, 4, 5, key='fish', next='w00t!')
            >>> mock.call_args
            call(3, 4, 5, key='fish', next='w00t!')

        `call_args`, along with members of the lists :attr:`call_args_list`,
        :attr:`method_calls` and :attr:`mock_calls` are :data:`call` objects.
        These are tuples, so they can be unpacked to get at the individual
        arguments and make more complex assertions. See
        :ref:`calls as tuples <calls-as-tuples>`.


    .. attribute:: call_args_list

        This is a list of all the calls made to the mock object in sequence
        (so the length of the list is the number of times it has been
        called). Before any calls have been made it is an empty list. The
        :data:`call` object can be used for conveniently constructing lists of
        calls to compare with `call_args_list`.

            >>> mock = Mock(return_value=None)
            >>> mock()
            >>> mock(3, 4)
            >>> mock(key='fish', next='w00t!')
            >>> mock.call_args_list
            [call(), call(3, 4), call(key='fish', next='w00t!')]
            >>> expected = [(), ((3, 4),), ({'key': 'fish', 'next': 'w00t!'},)]
            >>> mock.call_args_list == expected
            True

        Members of `call_args_list` are :data:`call` objects. These can be
        unpacked as tuples to get at the individual arguments. See
        :ref:`calls as tuples <calls-as-tuples>`.


    .. attribute:: method_calls

        As well as tracking calls to themselves, mocks also track calls to
        methods and attributes, and *their* methods and attributes:

            >>> mock = Mock()
            >>> mock.method()
            <Mock name='mock.method()' id='...'>
            >>> mock.property.method.attribute()
            <Mock name='mock.property.method.attribute()' id='...'>
            >>> mock.method_calls
            [call.method(), call.property.method.attribute()]

        Members of `method_calls` are :data:`call` objects. These can be
        unpacked as tuples to get at the individual arguments. See
        :ref:`calls as tuples <calls-as-tuples>`.


    .. attribute:: mock_calls

        `mock_calls` records *all* calls to the mock object, its methods, magic
        methods *and* return value mocks.

            >>> mock = MagicMock()
            >>> result = mock(1, 2, 3)
            >>> mock.first(a=3)
            <MagicMock name='mock.first()' id='...'>
            >>> mock.second()
            <MagicMock name='mock.second()' id='...'>
            >>> int(mock)
            1
            >>> result(1)
            <MagicMock name='mock()()' id='...'>
            >>> expected = [call(1, 2, 3), call.first(a=3), call.second(),
            ... call.__int__(), call()(1)]
            >>> mock.mock_calls == expected
            True

        Members of `mock_calls` are :data:`call` objects. These can be
        unpacked as tuples to get at the individual arguments. See
        :ref:`calls as tuples <calls-as-tuples>`.


    .. attribute:: __class__

        Normally the `__class__` attribute of an object will return its type.
        For a mock object with a `spec` `__class__` returns the spec class
        instead. This allows mock objects to pass `isinstance` tests for the
        object they are replacing / masquerading as:

            >>> mock = Mock(spec=3)
            >>> isinstance(mock, int)
            True

        `__class__` is assignable to, this allows a mock to pass an
        `isinstance` check without forcing you to use a spec:

            >>> mock = Mock()
            >>> mock.__class__ = dict
            >>> isinstance(mock, dict)
            True

.. class:: NonCallableMock(spec=None, wraps=None, name=None, spec_set=None, **kwargs)

    A non-callable version of `Mock`. The constructor parameters have the same
    meaning of `Mock`, with the exception of `return_value` and `side_effect`
    which have no meaning on a non-callable mock.

Mock objects that use a class or an instance as a `spec` or `spec_set` are able
to pass `isinstance` tests:

    >>> mock = Mock(spec=SomeClass)
    >>> isinstance(mock, SomeClass)
    True
    >>> mock = Mock(spec_set=SomeClass())
    >>> isinstance(mock, SomeClass)
    True

The `Mock` classes have support for mocking magic methods. See :ref:`magic
methods <magic-methods>` for the full details.

The mock classes and the :func:`patch` decorators all take arbitrary keyword
arguments for configuration. For the `patch` decorators the keywords are
passed to the constructor of the mock being created. The keyword arguments
are for configuring attributes of the mock:

        >>> m = MagicMock(attribute=3, other='fish')
        >>> m.attribute
        3
        >>> m.other
        'fish'

The return value and side effect of child mocks can be set in the same way,
using dotted notation. As you can't use dotted names directly in a call you
have to create a dictionary and unpack it using `**`:

    >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
    >>> mock = Mock(some_attribute='eggs', **attrs)
    >>> mock.some_attribute
    'eggs'
    >>> mock.method()
    3
    >>> mock.other()
    Traceback (most recent call last):
      ...
    KeyError

A callable mock which was created with a *spec* (or a *spec_set*) will
introspect the specification object's signature when matching calls to
the mock.  Therefore, it can match the actual call's arguments regardless
of whether they were passed positionally or by name::

   >>> def f(a, b, c): pass
   ...
   >>> mock = Mock(spec=f)
   >>> mock(1, 2, c=3)
   <Mock name='mock()' id='140161580456576'>
   >>> mock.assert_called_with(1, 2, 3)
   >>> mock.assert_called_with(a=1, b=2, c=3)

This applies to :meth:`~Mock.assert_called_with`,
:meth:`~Mock.assert_called_once_with`, :meth:`~Mock.assert_has_calls` and
:meth:`~Mock.assert_any_call`.  When :ref:`auto-speccing`, it will also
apply to method calls on the mock object.

   .. versionchanged:: 3.4
      Added signature introspection on specced and autospecced mock objects.


.. class:: PropertyMock(*args, **kwargs)

   A mock intended to be used as a property, or other descriptor, on a class.
   `PropertyMock` provides `__get__` and `__set__` methods so you can specify
   a return value when it is fetched.

   Fetching a `PropertyMock` instance from an object calls the mock, with
   no args. Setting it calls the mock with the value being set.

        >>> class Foo:
        ...     @property
        ...     def foo(self):
        ...         return 'something'
        ...     @foo.setter
        ...     def foo(self, value):
        ...         pass
        ...
        >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo:
        ...     mock_foo.return_value = 'mockity-mock'
        ...     this_foo = Foo()
        ...     print this_foo.foo
        ...     this_foo.foo = 6
        ...
        mockity-mock
        >>> mock_foo.mock_calls
        [call(), call(6)]

Because of the way mock attributes are stored you can't directly attach a
`PropertyMock` to a mock object. Instead you can attach it to the mock type
object::

    >>> m = MagicMock()
    >>> p = PropertyMock(return_value=3)
    >>> type(m).foo = p
    >>> m.foo
    3
    >>> p.assert_called_once_with()


Calling
~~~~~~~

Mock objects are callable. The call will return the value set as the
:attr:`~Mock.return_value` attribute. The default return value is a new Mock
object; it is created the first time the return value is accessed (either
explicitly or by calling the Mock) - but it is stored and the same one
returned each time.

Calls made to the object will be recorded in the attributes
like :attr:`~Mock.call_args` and :attr:`~Mock.call_args_list`.

If :attr:`~Mock.side_effect` is set then it will be called after the call has
been recorded, so if `side_effect` raises an exception the call is still
recorded.

The simplest way to make a mock raise an exception when called is to make
:attr:`~Mock.side_effect` an exception class or instance:

        >>> m = MagicMock(side_effect=IndexError)
        >>> m(1, 2, 3)
        Traceback (most recent call last):
          ...
        IndexError
        >>> m.mock_calls
        [call(1, 2, 3)]
        >>> m.side_effect = KeyError('Bang!')
        >>> m('two', 'three', 'four')
        Traceback (most recent call last):
          ...
        KeyError: 'Bang!'
        >>> m.mock_calls
        [call(1, 2, 3), call('two', 'three', 'four')]

If `side_effect` is a function then whatever that function returns is what
calls to the mock return. The `side_effect` function is called with the
same arguments as the mock. This allows you to vary the return value of the
call dynamically, based on the input:

        >>> def side_effect(value):
        ...     return value + 1
        ...
        >>> m = MagicMock(side_effect=side_effect)
        >>> m(1)
        2
        >>> m(2)
        3
        >>> m.mock_calls
        [call(1), call(2)]

If you want the mock to still return the default return value (a new mock), or
any set return value, then there are two ways of doing this. Either return
`mock.return_value` from inside `side_effect`, or return :data:`DEFAULT`:

        >>> m = MagicMock()
        >>> def side_effect(*args, **kwargs):
        ...     return m.return_value
        ...
        >>> m.side_effect = side_effect
        >>> m.return_value = 3
        >>> m()
        3
        >>> def side_effect(*args, **kwargs):
        ...     return DEFAULT
        ...
        >>> m.side_effect = side_effect
        >>> m()
        3

To remove a `side_effect`, and return to the default behaviour, set the
`side_effect` to `None`:

        >>> m = MagicMock(return_value=6)
        >>> def side_effect(*args, **kwargs):
        ...     return 3
        ...
        >>> m.side_effect = side_effect
        >>> m()
        3
        >>> m.side_effect = None
        >>> m()
        6

The `side_effect` can also be any iterable object. Repeated calls to the mock
will return values from the iterable (until the iterable is exhausted and
a `StopIteration` is raised):

        >>> m = MagicMock(side_effect=[1, 2, 3])
        >>> m()
        1
        >>> m()
        2
        >>> m()
        3
        >>> m()
        Traceback (most recent call last):
          ...
        StopIteration

If any members of the iterable are exceptions they will be raised instead of
returned::

        >>> iterable = (33, ValueError, 66)
        >>> m = MagicMock(side_effect=iterable)
        >>> m()
        33
        >>> m()
        Traceback (most recent call last):
         ...
        ValueError
        >>> m()
        66


.. _deleting-attributes:

Deleting Attributes
~~~~~~~~~~~~~~~~~~~

Mock objects create attributes on demand. This allows them to pretend to be
objects of any type.

You may want a mock object to return `False` to a `hasattr` call, or raise an
`AttributeError` when an attribute is fetched. You can do this by providing
an object as a `spec` for a mock, but that isn't always convenient.

You "block" attributes by deleting them. Once deleted, accessing an attribute
will raise an `AttributeError`.

    >>> mock = MagicMock()
    >>> hasattr(mock, 'm')
    True
    >>> del mock.m
    >>> hasattr(mock, 'm')
    False
    >>> del mock.f
    >>> mock.f
    Traceback (most recent call last):
        ...
    AttributeError: f


Mock names and the name attribute
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Since "name" is an argument to the :class:`Mock` constructor, if you want your
mock object to have a "name" attribute you can't just pass it in at creation
time. There are two alternatives. One option is to use
:meth:`~Mock.configure_mock`::

    >>> mock = MagicMock()
    >>> mock.configure_mock(name='my_name')
    >>> mock.name
    'my_name'

A simpler option is to simply set the "name" attribute after mock creation::

    >>> mock = MagicMock()
    >>> mock.name = "foo"


Attaching Mocks as Attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When you attach a mock as an attribute of another mock (or as the return
value) it becomes a "child" of that mock. Calls to the child are recorded in
the :attr:`~Mock.method_calls` and :attr:`~Mock.mock_calls` attributes of the
parent. This is useful for configuring child mocks and then attaching them to
the parent, or for attaching mocks to a parent that records all calls to the
children and allows you to make assertions about the order of calls between
mocks:

    >>> parent = MagicMock()
    >>> child1 = MagicMock(return_value=None)
    >>> child2 = MagicMock(return_value=None)
    >>> parent.child1 = child1
    >>> parent.child2 = child2
    >>> child1(1)
    >>> child2(2)
    >>> parent.mock_calls
    [call.child1(1), call.child2(2)]

The exception to this is if the mock has a name. This allows you to prevent
the "parenting" if for some reason you don't want it to happen.

    >>> mock = MagicMock()
    >>> not_a_child = MagicMock(name='not-a-child')
    >>> mock.attribute = not_a_child
    >>> mock.attribute()
    <MagicMock name='not-a-child()' id='...'>
    >>> mock.mock_calls
    []

Mocks created for you by :func:`patch` are automatically given names. To
attach mocks that have names to a parent you use the :meth:`~Mock.attach_mock`
method:

    >>> thing1 = object()
    >>> thing2 = object()
    >>> parent = MagicMock()
    >>> with patch('__main__.thing1', return_value=None) as child1:
    ...     with patch('__main__.thing2', return_value=None) as child2:
    ...         parent.attach_mock(child1, 'child1')
    ...         parent.attach_mock(child2, 'child2')
    ...         child1('one')
    ...         child2('two')
    ...
    >>> parent.mock_calls
    [call.child1('one'), call.child2('two')]


.. [#] The only exceptions are magic methods and attributes (those that have
       leading and trailing double underscores). Mock doesn't create these but
       instead of raises an ``AttributeError``. This is because the interpreter
       will often implicitly request these methods, and gets *very* confused to
       get a new Mock object when it expects a magic method. If you need magic
       method support see :ref:`magic methods <magic-methods>`.


The patchers
------------

The patch decorators are used for patching objects only within the scope of
the function they decorate. They automatically handle the unpatching for you,
even if exceptions are raised. All of these functions can also be used in with
statements or as class decorators.


patch
~~~~~

.. note::

    `patch` is straightforward to use. The key is to do the patching in the
    right namespace. See the section `where to patch`_.

.. function:: patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

    `patch` acts as a function decorator, class decorator or a context
    manager. Inside the body of the function or with statement, the `target`
    is patched with a `new` object. When the function/with statement exits
    the patch is undone.

    If `new` is omitted, then the target is replaced with a
    :class:`MagicMock`. If `patch` is used as a decorator and `new` is
    omitted, the created mock is passed in as an extra argument to the
    decorated function. If `patch` is used as a context manager the created
    mock is returned by the context manager.

    `target` should be a string in the form `'package.module.ClassName'`. The
    `target` is imported and the specified object replaced with the `new`
    object, so the `target` must be importable from the environment you are
    calling `patch` from. The target is imported when the decorated function
    is executed, not at decoration time.

    The `spec` and `spec_set` keyword arguments are passed to the `MagicMock`
    if patch is creating one for you.

    In addition you can pass `spec=True` or `spec_set=True`, which causes
    patch to pass in the object being mocked as the spec/spec_set object.

    `new_callable` allows you to specify a different class, or callable object,
    that will be called to create the `new` object. By default `MagicMock` is
    used.

    A more powerful form of `spec` is `autospec`. If you set `autospec=True`
    then the mock with be created with a spec from the object being replaced.
    All attributes of the mock will also have the spec of the corresponding
    attribute of the object being replaced. Methods and functions being mocked
    will have their arguments checked and will raise a `TypeError` if they are
    called with the wrong signature. For mocks
    replacing a class, their return value (the 'instance') will have the same
    spec as the class. See the :func:`create_autospec` function and
    :ref:`auto-speccing`.

    Instead of `autospec=True` you can pass `autospec=some_object` to use an
    arbitrary object as the spec instead of the one being replaced.

    By default `patch` will fail to replace attributes that don't exist. If
    you pass in `create=True`, and the attribute doesn't exist, patch will
    create the attribute for you when the patched function is called, and
    delete it again afterwards. This is useful for writing tests against
    attributes that your production code creates at runtime. It is off by
    default because it can be dangerous. With it switched on you can write
    passing tests against APIs that don't actually exist!

    Patch can be used as a `TestCase` class decorator. It works by
    decorating each test method in the class. This reduces the boilerplate
    code when your test methods share a common patchings set. `patch` finds
    tests by looking for method names that start with `patch.TEST_PREFIX`.
    By default this is `test`, which matches the way `unittest` finds tests.
    You can specify an alternative prefix by setting `patch.TEST_PREFIX`.

    Patch can be used as a context manager, with the with statement. Here the
    patching applies to the indented block after the with statement. If you
    use "as" then the patched object will be bound to the name after the
    "as"; very useful if `patch` is creating a mock object for you.

    `patch` takes arbitrary keyword arguments. These will be passed to
    the `Mock` (or `new_callable`) on construction.

    `patch.dict(...)`, `patch.multiple(...)` and `patch.object(...)` are
    available for alternate use-cases.

`patch` as function decorator, creating the mock for you and passing it into
the decorated function:

    >>> @patch('__main__.SomeClass')
    ... def function(normal_argument, mock_class):
    ...     print(mock_class is SomeClass)
    ...
    >>> function(None)
    True

Patching a class replaces the class with a `MagicMock` *instance*. If the
class is instantiated in the code under test then it will be the
:attr:`~Mock.return_value` of the mock that will be used.

If the class is instantiated multiple times you could use
:attr:`~Mock.side_effect` to return a new mock each time. Alternatively you
can set the `return_value` to be anything you want.

To configure return values on methods of *instances* on the patched class
you must do this on the `return_value`. For example:

    >>> class Class:
    ...     def method(self):
    ...         pass
    ...
    >>> with patch('__main__.Class') as MockClass:
    ...     instance = MockClass.return_value
    ...     instance.method.return_value = 'foo'
    ...     assert Class() is instance
    ...     assert Class().method() == 'foo'
    ...

If you use `spec` or `spec_set` and `patch` is replacing a *class*, then the
return value of the created mock will have the same spec.

    >>> Original = Class
    >>> patcher = patch('__main__.Class', spec=True)
    >>> MockClass = patcher.start()
    >>> instance = MockClass()
    >>> assert isinstance(instance, Original)
    >>> patcher.stop()

The `new_callable` argument is useful where you want to use an alternative
class to the default :class:`MagicMock` for the created mock. For example, if
you wanted a :class:`NonCallableMock` to be used:

    >>> thing = object()
    >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing:
    ...     assert thing is mock_thing
    ...     thing()
    ...
    Traceback (most recent call last):
      ...
    TypeError: 'NonCallableMock' object is not callable

Another use case might be to replace an object with a `StringIO` instance:

    >>> from StringIO import StringIO
    >>> def foo():
    ...     print 'Something'
    ...
    >>> @patch('sys.stdout', new_callable=StringIO)
    ... def test(mock_stdout):
    ...     foo()
    ...     assert mock_stdout.getvalue() == 'Something\n'
    ...
    >>> test()

When `patch` is creating a mock for you, it is common that the first thing
you need to do is to configure the mock. Some of that configuration can be done
in the call to patch. Any arbitrary keywords you pass into the call will be
used to set attributes on the created mock:

    >>> patcher = patch('__main__.thing', first='one', second='two')
    >>> mock_thing = patcher.start()
    >>> mock_thing.first
    'one'
    >>> mock_thing.second
    'two'

As well as attributes on the created mock attributes, like the
:attr:`~Mock.return_value` and :attr:`~Mock.side_effect`, of child mocks can
also be configured. These aren't syntactically valid to pass in directly as
keyword arguments, but a dictionary with these as keys can still be expanded
into a `patch` call using `**`:

    >>> config = {'method.return_value': 3, 'other.side_effect': KeyError}
    >>> patcher = patch('__main__.thing', **config)
    >>> mock_thing = patcher.start()
    >>> mock_thing.method()
    3
    >>> mock_thing.other()
    Traceback (most recent call last):
      ...
    KeyError


patch.object
~~~~~~~~~~~~

.. function:: patch.object(target, attribute, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

    patch the named member (`attribute`) on an object (`target`) with a mock
    object.

    `patch.object` can be used as a decorator, class decorator or a context
    manager. Arguments `new`, `spec`, `create`, `spec_set`, `autospec` and
    `new_callable` have the same meaning as for `patch`. Like `patch`,
    `patch.object` takes arbitrary keyword arguments for configuring the mock
    object it creates.

    When used as a class decorator `patch.object` honours `patch.TEST_PREFIX`
    for choosing which methods to wrap.

You can either call `patch.object` with three arguments or two arguments. The
three argument form takes the object to be patched, the attribute name and the
object to replace the attribute with.

When calling with the two argument form you omit the replacement object, and a
mock is created for you and passed in as an extra argument to the decorated
function:

    >>> @patch.object(SomeClass, 'class_method')
    ... def test(mock_method):
    ...     SomeClass.class_method(3)
    ...     mock_method.assert_called_with(3)
    ...
    >>> test()

`spec`, `create` and the other arguments to `patch.object` have the same
meaning as they do for `patch`.


patch.dict
~~~~~~~~~~

.. function:: patch.dict(in_dict, values=(), clear=False, **kwargs)

    Patch a dictionary, or dictionary like object, and restore the dictionary
    to its original state after the test.

    `in_dict` can be a dictionary or a mapping like container. If it is a
    mapping then it must at least support getting, setting and deleting items
    plus iterating over keys.

    `in_dict` can also be a string specifying the name of the dictionary, which
    will then be fetched by importing it.

    `values` can be a dictionary of values to set in the dictionary. `values`
    can also be an iterable of `(key, value)` pairs.

    If `clear` is True then the dictionary will be cleared before the new
    values are set.

    `patch.dict` can also be called with arbitrary keyword arguments to set
    values in the dictionary.

    `patch.dict` can be used as a context manager, decorator or class
    decorator. When used as a class decorator `patch.dict` honours
    `patch.TEST_PREFIX` for choosing which methods to wrap.

`patch.dict` can be used to add members to a dictionary, or simply let a test
change a dictionary, and ensure the dictionary is restored when the test
ends.

    >>> foo = {}
    >>> with patch.dict(foo, {'newkey': 'newvalue'}):
    ...     assert foo == {'newkey': 'newvalue'}
    ...
    >>> assert foo == {}

    >>> import os
    >>> with patch.dict('os.environ', {'newkey': 'newvalue'}):
    ...     print os.environ['newkey']
    ...
    newvalue
    >>> assert 'newkey' not in os.environ

Keywords can be used in the `patch.dict` call to set values in the dictionary:

    >>> mymodule = MagicMock()
    >>> mymodule.function.return_value = 'fish'
    >>> with patch.dict('sys.modules', mymodule=mymodule):
    ...     import mymodule
    ...     mymodule.function('some', 'args')
    ...
    'fish'

`patch.dict` can be used with dictionary like objects that aren't actually
dictionaries. At the very minimum they must support item getting, setting,
deleting and either iteration or membership test. This corresponds to the
magic methods `__getitem__`, `__setitem__`, `__delitem__` and either
`__iter__` or `__contains__`.

    >>> class Container:
    ...     def __init__(self):
    ...         self.values = {}
    ...     def __getitem__(self, name):
    ...         return self.values[name]
    ...     def __setitem__(self, name, value):
    ...         self.values[name] = value
    ...     def __delitem__(self, name):
    ...         del self.values[name]
    ...     def __iter__(self):
    ...         return iter(self.values)
    ...
    >>> thing = Container()
    >>> thing['one'] = 1
    >>> with patch.dict(thing, one=2, two=3):
    ...     assert thing['one'] == 2
    ...     assert thing['two'] == 3
    ...
    >>> assert thing['one'] == 1
    >>> assert list(thing) == ['one']


patch.multiple
~~~~~~~~~~~~~~

.. function:: patch.multiple(target, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

    Perform multiple patches in a single call. It takes the object to be
    patched (either as an object or a string to fetch the object by importing)
    and keyword arguments for the patches::

        with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'):
            ...

    Use :data:`DEFAULT` as the value if you want `patch.multiple` to create
    mocks for you. In this case the created mocks are passed into a decorated
    function by keyword, and a dictionary is returned when `patch.multiple` is
    used as a context manager.

    `patch.multiple` can be used as a decorator, class decorator or a context
    manager. The arguments `spec`, `spec_set`, `create`, `autospec` and
    `new_callable` have the same meaning as for `patch`. These arguments will
    be applied to *all* patches done by `patch.multiple`.

    When used as a class decorator `patch.multiple` honours `patch.TEST_PREFIX`
    for choosing which methods to wrap.

If you want `patch.multiple` to create mocks for you, then you can use
:data:`DEFAULT` as the value. If you use `patch.multiple` as a decorator
then the created mocks are passed into the decorated function by keyword.

    >>> thing = object()
    >>> other = object()

    >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
    ... def test_function(thing, other):
    ...     assert isinstance(thing, MagicMock)
    ...     assert isinstance(other, MagicMock)
    ...
    >>> test_function()

`patch.multiple` can be nested with other `patch` decorators, but put arguments
passed by keyword *after* any of the standard arguments created by `patch`:

    >>> @patch('sys.exit')
    ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
    ... def test_function(mock_exit, other, thing):
    ...     assert 'other' in repr(other)
    ...     assert 'thing' in repr(thing)
    ...     assert 'exit' in repr(mock_exit)
    ...
    >>> test_function()

If `patch.multiple` is used as a context manager, the value returned by the
context manger is a dictionary where created mocks are keyed by name:

    >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values:
    ...     assert 'other' in repr(values['other'])
    ...     assert 'thing' in repr(values['thing'])
    ...     assert values['thing'] is thing
    ...     assert values['other'] is other
    ...


.. _start-and-stop:

patch methods: start and stop
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

All the patchers have `start` and `stop` methods. These make it simpler to do
patching in `setUp` methods or where you want to do multiple patches without
nesting decorators or with statements.

To use them call `patch`, `patch.object` or `patch.dict` as normal and keep a
reference to the returned `patcher` object. You can then call `start` to put
the patch in place and `stop` to undo it.

If you are using `patch` to create a mock for you then it will be returned by
the call to `patcher.start`.

    >>> patcher = patch('package.module.ClassName')
    >>> from package import module
    >>> original = module.ClassName
    >>> new_mock = patcher.start()
    >>> assert module.ClassName is not original
    >>> assert module.ClassName is new_mock
    >>> patcher.stop()
    >>> assert module.ClassName is original
    >>> assert module.ClassName is not new_mock


A typical use case for this might be for doing multiple patches in the `setUp`
method of a `TestCase`:

    >>> class MyTest(TestCase):
    ...     def setUp(self):
    ...         self.patcher1 = patch('package.module.Class1')
    ...         self.patcher2 = patch('package.module.Class2')
    ...         self.MockClass1 = self.patcher1.start()
    ...         self.MockClass2 = self.patcher2.start()
    ...
    ...     def tearDown(self):
    ...         self.patcher1.stop()
    ...         self.patcher2.stop()
    ...
    ...     def test_something(self):
    ...         assert package.module.Class1 is self.MockClass1
    ...         assert package.module.Class2 is self.MockClass2
    ...
    >>> MyTest('test_something').run()

.. caution::

    If you use this technique you must ensure that the patching is "undone" by
    calling `stop`. This can be fiddlier than you might think, because if an
    exception is raised in the ``setUp`` then ``tearDown`` is not called.
    :meth:`unittest.TestCase.addCleanup` makes this easier:

        >>> class MyTest(TestCase):
        ...     def setUp(self):
        ...         patcher = patch('package.module.Class')
        ...         self.MockClass = patcher.start()
        ...         self.addCleanup(patcher.stop)
        ...
        ...     def test_something(self):
        ...         assert package.module.Class is self.MockClass
        ...

    As an added bonus you no longer need to keep a reference to the `patcher`
    object.

It is also possible to stop all patches which have been started by using
`patch.stopall`.

.. function:: patch.stopall

    Stop all active patches. Only stops patches started with `start`.


TEST_PREFIX
~~~~~~~~~~~

All of the patchers can be used as class decorators. When used in this way
they wrap every test method on the class. The patchers recognise methods that
start with `test` as being test methods. This is the same way that the
:class:`unittest.TestLoader` finds test methods by default.

It is possible that you want to use a different prefix for your tests. You can
inform the patchers of the different prefix by setting `patch.TEST_PREFIX`:

    >>> patch.TEST_PREFIX = 'foo'
    >>> value = 3
    >>>
    >>> @patch('__main__.value', 'not three')
    ... class Thing:
    ...     def foo_one(self):
    ...         print value
    ...     def foo_two(self):
    ...         print value
    ...
    >>>
    >>> Thing().foo_one()
    not three
    >>> Thing().foo_two()
    not three
    >>> value
    3


Nesting Patch Decorators
~~~~~~~~~~~~~~~~~~~~~~~~

If you want to perform multiple patches then you can simply stack up the
decorators.

You can stack up multiple patch decorators using this pattern:

    >>> @patch.object(SomeClass, 'class_method')
    ... @patch.object(SomeClass, 'static_method')
    ... def test(mock1, mock2):
    ...     assert SomeClass.static_method is mock1
    ...     assert SomeClass.class_method is mock2
    ...     SomeClass.static_method('foo')
    ...     SomeClass.class_method('bar')
    ...     return mock1, mock2
    ...
    >>> mock1, mock2 = test()
    >>> mock1.assert_called_once_with('foo')
    >>> mock2.assert_called_once_with('bar')


Note that the decorators are applied from the bottom upwards. This is the
standard way that Python applies decorators. The order of the created mocks
passed into your test function matches this order.


.. _where-to-patch:

Where to patch
~~~~~~~~~~~~~~

`patch` works by (temporarily) changing the object that a *name* points to with
another one. There can be many names pointing to any individual object, so
for patching to work you must ensure that you patch the name used by the system
under test.

The basic principle is that you patch where an object is *looked up*, which
is not necessarily the same place as where it is defined. A couple of
examples will help to clarify this.

Imagine we have a project that we want to test with the following structure::

    a.py
        -> Defines SomeClass

    b.py
        -> from a import SomeClass
        -> some_function instantiates SomeClass

Now we want to test `some_function` but we want to mock out `SomeClass` using
`patch`. The problem is that when we import module b, which we will have to
do then it imports `SomeClass` from module a. If we use `patch` to mock out
`a.SomeClass` then it will have no effect on our test; module b already has a
reference to the *real* `SomeClass` and it looks like our patching had no
effect.

The key is to patch out `SomeClass` where it is used (or where it is looked up
). In this case `some_function` will actually look up `SomeClass` in module b,
where we have imported it. The patching should look like::

    @patch('b.SomeClass')

However, consider the alternative scenario where instead of `from a import
SomeClass` module b does `import a` and `some_function` uses `a.SomeClass`. Both
of these import forms are common. In this case the class we want to patch is
being looked up on the a module and so we have to patch `a.SomeClass` instead::

    @patch('a.SomeClass')


Patching Descriptors and Proxy Objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Both patch_ and patch.object_ correctly patch and restore descriptors: class
methods, static methods and properties. You should patch these on the *class*
rather than an instance. They also work with *some* objects
that proxy attribute access, like the `django setttings object
<http://www.voidspace.org.uk/python/weblog/arch_d7_2010_12_04.shtml#e1198>`_.


MagicMock and magic method support
----------------------------------

.. _magic-methods:

Mocking Magic Methods
~~~~~~~~~~~~~~~~~~~~~

:class:`Mock` supports mocking the Python protocol methods, also known as
"magic methods". This allows mock objects to replace containers or other
objects that implement Python protocols.

Because magic methods are looked up differently from normal methods [#]_, this
support has been specially implemented. This means that only specific magic
methods are supported. The supported list includes *almost* all of them. If
there are any missing that you need please let us know.

You mock magic methods by setting the method you are interested in to a function
or a mock instance. If you are using a function then it *must* take ``self`` as
the first argument [#]_.

   >>> def __str__(self):
   ...     return 'fooble'
   ...
   >>> mock = Mock()
   >>> mock.__str__ = __str__
   >>> str(mock)
   'fooble'

   >>> mock = Mock()
   >>> mock.__str__ = Mock()
   >>> mock.__str__.return_value = 'fooble'
   >>> str(mock)
   'fooble'

   >>> mock = Mock()
   >>> mock.__iter__ = Mock(return_value=iter([]))
   >>> list(mock)
   []

One use case for this is for mocking objects used as context managers in a
`with` statement:

   >>> mock = Mock()
   >>> mock.__enter__ = Mock(return_value='foo')
   >>> mock.__exit__ = Mock(return_value=False)
   >>> with mock as m:
   ...     assert m == 'foo'
   ...
   >>> mock.__enter__.assert_called_with()
   >>> mock.__exit__.assert_called_with(None, None, None)

Calls to magic methods do not appear in :attr:`~Mock.method_calls`, but they
are recorded in :attr:`~Mock.mock_calls`.

.. note::

   If you use the `spec` keyword argument to create a mock then attempting to
   set a magic method that isn't in the spec will raise an `AttributeError`.

The full list of supported magic methods is:

* ``__hash__``, ``__sizeof__``, ``__repr__`` and ``__str__``
* ``__dir__``, ``__format__`` and ``__subclasses__``
* ``__floor__``, ``__trunc__`` and ``__ceil__``
* Comparisons: ``__cmp__``, ``__lt__``, ``__gt__``, ``__le__``, ``__ge__``,
  ``__eq__`` and ``__ne__``
* Container methods: ``__getitem__``, ``__setitem__``, ``__delitem__``,
  ``__contains__``, ``__len__``, ``__iter__``, ``__getslice__``,
  ``__setslice__``, ``__reversed__`` and ``__missing__``
* Context manager: ``__enter__`` and ``__exit__``
* Unary numeric methods: ``__neg__``, ``__pos__`` and ``__invert__``
* The numeric methods (including right hand and in-place variants):
  ``__add__``, ``__sub__``, ``__mul__``, ``__div__``,
  ``__floordiv__``, ``__mod__``, ``__divmod__``, ``__lshift__``,
  ``__rshift__``, ``__and__``, ``__xor__``, ``__or__``, and ``__pow__``
* Numeric conversion methods: ``__complex__``, ``__int__``, ``__float__``,
  ``__index__`` and ``__coerce__``
* Descriptor methods: ``__get__``, ``__set__`` and ``__delete__``
* Pickling: ``__reduce__``, ``__reduce_ex__``, ``__getinitargs__``,
  ``__getnewargs__``, ``__getstate__`` and ``__setstate__``


The following methods exist but are *not* supported as they are either in use
by mock, can't be set dynamically, or can cause problems:

* ``__getattr__``, ``__setattr__``, ``__init__`` and ``__new__``
* ``__prepare__``, ``__instancecheck__``, ``__subclasscheck__``, ``__del__``



Magic Mock
~~~~~~~~~~

There are two `MagicMock` variants: `MagicMock` and `NonCallableMagicMock`.


.. class:: MagicMock(*args, **kw)

   ``MagicMock`` is a subclass of :class:`Mock` with default implementations
   of most of the magic methods. You can use ``MagicMock`` without having to
   configure the magic methods yourself.

   The constructor parameters have the same meaning as for :class:`Mock`.

   If you use the `spec` or `spec_set` arguments then *only* magic methods
   that exist in the spec will be created.


.. class:: NonCallableMagicMock(*args, **kw)

    A non-callable version of `MagicMock`.

    The constructor parameters have the same meaning as for
    :class:`MagicMock`, with the exception of `return_value` and
    `side_effect` which have no meaning on a non-callable mock.

The magic methods are setup with `MagicMock` objects, so you can configure them
and use them in the usual way:

   >>> mock = MagicMock()
   >>> mock[3] = 'fish'
   >>> mock.__setitem__.assert_called_with(3, 'fish')
   >>> mock.__getitem__.return_value = 'result'
   >>> mock[2]
   'result'

By default many of the protocol methods are required to return objects of a
specific type. These methods are preconfigured with a default return value, so
that they can be used without you having to do anything if you aren't interested
in the return value. You can still *set* the return value manually if you want
to change the default.

Methods and their defaults:

* ``__lt__``: NotImplemented
* ``__gt__``: NotImplemented
* ``__le__``: NotImplemented
* ``__ge__``: NotImplemented
* ``__int__`` : 1
* ``__contains__`` : False
* ``__len__`` : 1
* ``__iter__`` : iter([])
* ``__exit__`` : False
* ``__complex__`` : 1j
* ``__float__`` : 1.0
* ``__bool__`` : True
* ``__index__`` : 1
* ``__hash__`` : default hash for the mock
* ``__str__`` : default str for the mock
* ``__sizeof__``: default sizeof for the mock

For example:

   >>> mock = MagicMock()
   >>> int(mock)
   1
   >>> len(mock)
   0
   >>> list(mock)
   []
   >>> object() in mock
   False

The two equality method, `__eq__` and `__ne__`, are special.
They do the default equality comparison on identity, using a side
effect, unless you change their return value to return something else:

   >>> MagicMock() == 3
   False
   >>> MagicMock() != 3
   True
   >>> mock = MagicMock()
   >>> mock.__eq__.return_value = True
   >>> mock == 3
   True

The return value of `MagicMock.__iter__` can be any iterable object and isn't
required to be an iterator:

   >>> mock = MagicMock()
   >>> mock.__iter__.return_value = ['a', 'b', 'c']
   >>> list(mock)
   ['a', 'b', 'c']
   >>> list(mock)
   ['a', 'b', 'c']

If the return value *is* an iterator, then iterating over it once will consume
it and subsequent iterations will result in an empty list:

   >>> mock.__iter__.return_value = iter(['a', 'b', 'c'])
   >>> list(mock)
   ['a', 'b', 'c']
   >>> list(mock)
   []

``MagicMock`` has all of the supported magic methods configured except for some
of the obscure and obsolete ones. You can still set these up if you want.

Magic methods that are supported but not setup by default in ``MagicMock`` are:

* ``__subclasses__``
* ``__dir__``
* ``__format__``
* ``__get__``, ``__set__`` and ``__delete__``
* ``__reversed__`` and ``__missing__``
* ``__reduce__``, ``__reduce_ex__``, ``__getinitargs__``, ``__getnewargs__``,
  ``__getstate__`` and ``__setstate__``
* ``__getformat__`` and ``__setformat__``



.. [#] Magic methods *should* be looked up on the class rather than the
   instance. Different versions of Python are inconsistent about applying this
   rule. The supported protocol methods should work with all supported versions
   of Python.
.. [#] The function is basically hooked up to the class, but each ``Mock``
   instance is kept isolated from the others.


Helpers
-------

sentinel
~~~~~~~~

.. data:: sentinel

    The ``sentinel`` object provides a convenient way of providing unique
    objects for your tests.

    Attributes are created on demand when you access them by name. Accessing
    the same attribute will always return the same object. The objects
    returned have a sensible repr so that test failure messages are readable.

Sometimes when testing you need to test that a specific object is passed as an
argument to another method, or returned. It can be common to create named
sentinel objects to test this. `sentinel` provides a convenient way of
creating and testing the identity of objects like this.

In this example we monkey patch `method` to return `sentinel.some_object`:

    >>> real = ProductionClass()
    >>> real.method = Mock(name="method")
    >>> real.method.return_value = sentinel.some_object
    >>> result = real.method()
    >>> assert result is sentinel.some_object
    >>> sentinel.some_object
    sentinel.some_object


DEFAULT
~~~~~~~


.. data:: DEFAULT

    The `DEFAULT` object is a pre-created sentinel (actually
    `sentinel.DEFAULT`). It can be used by :attr:`~Mock.side_effect`
    functions to indicate that the normal return value should be used.


call
~~~~

.. function:: call(*args, **kwargs)

    `call` is a helper object for making simpler assertions, for comparing with
    :attr:`~Mock.call_args`, :attr:`~Mock.call_args_list`,
    :attr:`~Mock.mock_calls` and :attr:`~Mock.method_calls`. `call` can also be
    used with :meth:`~Mock.assert_has_calls`.

        >>> m = MagicMock(return_value=None)
        >>> m(1, 2, a='foo', b='bar')
        >>> m()
        >>> m.call_args_list == [call(1, 2, a='foo', b='bar'), call()]
        True

.. method:: call.call_list()

    For a call object that represents multiple calls, `call_list`
    returns a list of all the intermediate calls as well as the
    final call.

`call_list` is particularly useful for making assertions on "chained calls". A
chained call is multiple calls on a single line of code. This results in
multiple entries in :attr:`~Mock.mock_calls` on a mock. Manually constructing
the sequence of calls can be tedious.

:meth:`~call.call_list` can construct the sequence of calls from the same
chained call:

    >>> m = MagicMock()
    >>> m(1).method(arg='foo').other('bar')(2.0)
    <MagicMock name='mock().method().other()()' id='...'>
    >>> kall = call(1).method(arg='foo').other('bar')(2.0)
    >>> kall.call_list()
    [call(1),
     call().method(arg='foo'),
     call().method().other('bar'),
     call().method().other()(2.0)]
    >>> m.mock_calls == kall.call_list()
    True

.. _calls-as-tuples:

A `call` object is either a tuple of (positional args, keyword args) or
(name, positional args, keyword args) depending on how it was constructed. When
you construct them yourself this isn't particularly interesting, but the `call`
objects that are in the :attr:`Mock.call_args`, :attr:`Mock.call_args_list` and
:attr:`Mock.mock_calls` attributes can be introspected to get at the individual
arguments they contain.

The `call` objects in :attr:`Mock.call_args` and :attr:`Mock.call_args_list`
are two-tuples of (positional args, keyword args) whereas the `call` objects
in :attr:`Mock.mock_calls`, along with ones you construct yourself, are
three-tuples of (name, positional args, keyword args).

You can use their "tupleness" to pull out the individual arguments for more
complex introspection and assertions. The positional arguments are a tuple
(an empty tuple if there are no positional arguments) and the keyword
arguments are a dictionary:

    >>> m = MagicMock(return_value=None)
    >>> m(1, 2, 3, arg='one', arg2='two')
    >>> kall = m.call_args
    >>> args, kwargs = kall
    >>> args
    (1, 2, 3)
    >>> kwargs
    {'arg2': 'two', 'arg': 'one'}
    >>> args is kall[0]
    True
    >>> kwargs is kall[1]
    True

    >>> m = MagicMock()
    >>> m.foo(4, 5, 6, arg='two', arg2='three')
    <MagicMock name='mock.foo()' id='...'>
    >>> kall = m.mock_calls[0]
    >>> name, args, kwargs = kall
    >>> name
    'foo'
    >>> args
    (4, 5, 6)
    >>> kwargs
    {'arg2': 'three', 'arg': 'two'}
    >>> name is m.mock_calls[0][0]
    True


create_autospec
~~~~~~~~~~~~~~~

.. function:: create_autospec(spec, spec_set=False, instance=False, **kwargs)

    Create a mock object using another object as a spec. Attributes on the
    mock will use the corresponding attribute on the `spec` object as their
    spec.

    Functions or methods being mocked will have their arguments checked to
    ensure that they are called with the correct signature.

    If `spec_set` is `True` then attempting to set attributes that don't exist
    on the spec object will raise an `AttributeError`.

    If a class is used as a spec then the return value of the mock (the
    instance of the class) will have the same spec. You can use a class as the
    spec for an instance object by passing `instance=True`. The returned mock
    will only be callable if instances of the mock are callable.

    `create_autospec` also takes arbitrary keyword arguments that are passed to
    the constructor of the created mock.

See :ref:`auto-speccing` for examples of how to use auto-speccing with
`create_autospec` and the `autospec` argument to :func:`patch`.


ANY
~~~

.. data:: ANY

Sometimes you may need to make assertions about *some* of the arguments in a
call to mock, but either not care about some of the arguments or want to pull
them individually out of :attr:`~Mock.call_args` and make more complex
assertions on them.

To ignore certain arguments you can pass in objects that compare equal to
*everything*. Calls to :meth:`~Mock.assert_called_with` and
:meth:`~Mock.assert_called_once_with` will then succeed no matter what was
passed in.

    >>> mock = Mock(return_value=None)
    >>> mock('foo', bar=object())
    >>> mock.assert_called_once_with('foo', bar=ANY)

`ANY` can also be used in comparisons with call lists like
:attr:`~Mock.mock_calls`:

    >>> m = MagicMock(return_value=None)
    >>> m(1)
    >>> m(1, 2)
    >>> m(object())
    >>> m.mock_calls == [call(1), call(1, 2), ANY]
    True



FILTER_DIR
~~~~~~~~~~

.. data:: FILTER_DIR

`FILTER_DIR` is a module level variable that controls the way mock objects
respond to `dir` (only for Python 2.6 or more recent). The default is `True`,
which uses the filtering described below, to only show useful members. If you
dislike this filtering, or need to switch it off for diagnostic purposes, then
set `mock.FILTER_DIR = False`.

With filtering on, `dir(some_mock)` shows only useful attributes and will
include any dynamically created attributes that wouldn't normally be shown.
If the mock was created with a `spec` (or `autospec` of course) then all the
attributes from the original are shown, even if they haven't been accessed
yet:

    >>> dir(Mock())
    ['assert_any_call',
     'assert_called_once_with',
     'assert_called_with',
     'assert_has_calls',
     'attach_mock',
     ...
    >>> from urllib import request
    >>> dir(Mock(spec=request))
    ['AbstractBasicAuthHandler',
     'AbstractDigestAuthHandler',
     'AbstractHTTPHandler',
     'BaseHandler',
     ...

Many of the not-very-useful (private to `Mock` rather than the thing being
mocked) underscore and double underscore prefixed attributes have been
filtered from the result of calling `dir` on a `Mock`. If you dislike this
behaviour you can switch it off by setting the module level switch
`FILTER_DIR`:

    >>> from unittest import mock
    >>> mock.FILTER_DIR = False
    >>> dir(mock.Mock())
    ['_NonCallableMock__get_return_value',
     '_NonCallableMock__get_side_effect',
     '_NonCallableMock__return_value_doc',
     '_NonCallableMock__set_return_value',
     '_NonCallableMock__set_side_effect',
     '__call__',
     '__class__',
     ...

Alternatively you can just use `vars(my_mock)` (instance members) and
`dir(type(my_mock))` (type members) to bypass the filtering irrespective of
`mock.FILTER_DIR`.


mock_open
~~~~~~~~~

.. function:: mock_open(mock=None, read_data=None)

    A helper function to create a mock to replace the use of `open`. It works
    for `open` called directly or used as a context manager.

    The `mock` argument is the mock object to configure. If `None` (the
    default) then a `MagicMock` will be created for you, with the API limited
    to methods or attributes available on standard file handles.

    `read_data` is a string for the `read`, `readline`, and `readlines` methods
    of the file handle to return.  Calls to those methods will take data from
    `read_data` until it is depleted.  The mock of these methods is pretty
    simplistic.  If you need more control over the data that you are feeding to
    the tested code you will need to customize this mock for yourself.
    `read_data` is an empty string by default.

Using `open` as a context manager is a great way to ensure your file handles
are closed properly and is becoming common::

    with open('/some/path', 'w') as f:
        f.write('something')

The issue is that even if you mock out the call to `open` it is the
*returned object* that is used as a context manager (and has `__enter__` and
`__exit__` called).

Mocking context managers with a :class:`MagicMock` is common enough and fiddly
enough that a helper function is useful.

    >>> m = mock_open()
    >>> with patch('__main__.open', m, create=True):
    ...     with open('foo', 'w') as h:
    ...         h.write('some stuff')
    ...
    >>> m.mock_calls
    [call('foo', 'w'),
     call().__enter__(),
     call().write('some stuff'),
     call().__exit__(None, None, None)]
    >>> m.assert_called_once_with('foo', 'w')
    >>> handle = m()
    >>> handle.write.assert_called_once_with('some stuff')

And for reading files:

    >>> with patch('__main__.open', mock_open(read_data='bibble'), create=True) as m:
    ...     with open('foo') as h:
    ...         result = h.read()
    ...
    >>> m.assert_called_once_with('foo')
    >>> assert result == 'bibble'


.. _auto-speccing:

Autospeccing
~~~~~~~~~~~~

Autospeccing is based on the existing `spec` feature of mock. It limits the
api of mocks to the api of an original object (the spec), but it is recursive
(implemented lazily) so that attributes of mocks only have the same api as
the attributes of the spec. In addition mocked functions / methods have the
same call signature as the original so they raise a `TypeError` if they are
called incorrectly.

Before I explain how auto-speccing works, here's why it is needed.

`Mock` is a very powerful and flexible object, but it suffers from two flaws
when used to mock out objects from a system under test. One of these flaws is
specific to the `Mock` api and the other is a more general problem with using
mock objects.

First the problem specific to `Mock`. `Mock` has two assert methods that are
extremely handy: :meth:`~Mock.assert_called_with` and
:meth:`~Mock.assert_called_once_with`.

    >>> mock = Mock(name='Thing', return_value=None)
    >>> mock(1, 2, 3)
    >>> mock.assert_called_once_with(1, 2, 3)
    >>> mock(1, 2, 3)
    >>> mock.assert_called_once_with(1, 2, 3)
    Traceback (most recent call last):
     ...
    AssertionError: Expected 'mock' to be called once. Called 2 times.

Because mocks auto-create attributes on demand, and allow you to call them
with arbitrary arguments, if you misspell one of these assert methods then
your assertion is gone:

.. code-block:: pycon

    >>> mock = Mock(name='Thing', return_value=None)
    >>> mock(1, 2, 3)
    >>> mock.assret_called_once_with(4, 5, 6)

Your tests can pass silently and incorrectly because of the typo.

The second issue is more general to mocking. If you refactor some of your
code, rename members and so on, any tests for code that is still using the
*old api* but uses mocks instead of the real objects will still pass. This
means your tests can all pass even though your code is broken.

Note that this is another reason why you need integration tests as well as
unit tests. Testing everything in isolation is all fine and dandy, but if you
don't test how your units are "wired together" there is still lots of room
for bugs that tests might have caught.

`mock` already provides a feature to help with this, called speccing. If you
use a class or instance as the `spec` for a mock then you can only access
attributes on the mock that exist on the real class:

    >>> from urllib import request
    >>> mock = Mock(spec=request.Request)
    >>> mock.assret_called_with
    Traceback (most recent call last):
     ...
    AttributeError: Mock object has no attribute 'assret_called_with'

The spec only applies to the mock itself, so we still have the same issue
with any methods on the mock:

.. code-block:: pycon

    >>> mock.has_data()
    <mock.Mock object at 0x...>
    >>> mock.has_data.assret_called_with()

Auto-speccing solves this problem. You can either pass `autospec=True` to
`patch` / `patch.object` or use the `create_autospec` function to create a
mock with a spec. If you use the `autospec=True` argument to `patch` then the
object that is being replaced will be used as the spec object. Because the
speccing is done "lazily" (the spec is created as attributes on the mock are
accessed) you can use it with very complex or deeply nested objects (like
modules that import modules that import modules) without a big performance
hit.

Here's an example of it in use:

    >>> from urllib import request
    >>> patcher = patch('__main__.request', autospec=True)
    >>> mock_request = patcher.start()
    >>> request is mock_request
    True
    >>> mock_request.Request
    <MagicMock name='request.Request' spec='Request' id='...'>

You can see that `request.Request` has a spec. `request.Request` takes two
arguments in the constructor (one of which is `self`). Here's what happens if
we try to call it incorrectly:

    >>> req = request.Request()
    Traceback (most recent call last):
     ...
    TypeError: <lambda>() takes at least 2 arguments (1 given)

The spec also applies to instantiated classes (i.e. the return value of
specced mocks):

    >>> req = request.Request('foo')
    >>> req
    <NonCallableMagicMock name='request.Request()' spec='Request' id='...'>

`Request` objects are not callable, so the return value of instantiating our
mocked out `request.Request` is a non-callable mock. With the spec in place
any typos in our asserts will raise the correct error:

    >>> req.add_header('spam', 'eggs')
    <MagicMock name='request.Request().add_header()' id='...'>
    >>> req.add_header.assret_called_with
    Traceback (most recent call last):
     ...
    AttributeError: Mock object has no attribute 'assret_called_with'
    >>> req.add_header.assert_called_with('spam', 'eggs')

In many cases you will just be able to add `autospec=True` to your existing
`patch` calls and then be protected against bugs due to typos and api
changes.

As well as using `autospec` through `patch` there is a
:func:`create_autospec` for creating autospecced mocks directly:

    >>> from urllib import request
    >>> mock_request = create_autospec(request)
    >>> mock_request.Request('foo', 'bar')
    <NonCallableMagicMock name='mock.Request()' spec='Request' id='...'>

This isn't without caveats and limitations however, which is why it is not
the default behaviour. In order to know what attributes are available on the
spec object, autospec has to introspect (access attributes) the spec. As you
traverse attributes on the mock a corresponding traversal of the original
object is happening under the hood. If any of your specced objects have
properties or descriptors that can trigger code execution then you may not be
able to use autospec. On the other hand it is much better to design your
objects so that introspection is safe [#]_.

A more serious problem is that it is common for instance attributes to be
created in the `__init__` method and not to exist on the class at all.
`autospec` can't know about any dynamically created attributes and restricts
the api to visible attributes.

    >>> class Something:
    ...   def __init__(self):
    ...     self.a = 33
    ...
    >>> with patch('__main__.Something', autospec=True):
    ...   thing = Something()
    ...   thing.a
    ...
    Traceback (most recent call last):
      ...
    AttributeError: Mock object has no attribute 'a'

There are a few different ways of resolving this problem. The easiest, but
not necessarily the least annoying, way is to simply set the required
attributes on the mock after creation. Just because `autospec` doesn't allow
you to fetch attributes that don't exist on the spec it doesn't prevent you
setting them:

    >>> with patch('__main__.Something', autospec=True):
    ...   thing = Something()
    ...   thing.a = 33
    ...

There is a more aggressive version of both `spec` and `autospec` that *does*
prevent you setting non-existent attributes. This is useful if you want to
ensure your code only *sets* valid attributes too, but obviously it prevents
this particular scenario:

    >>> with patch('__main__.Something', autospec=True, spec_set=True):
    ...   thing = Something()
    ...   thing.a = 33
    ...
    Traceback (most recent call last):
     ...
    AttributeError: Mock object has no attribute 'a'

Probably the best way of solving the problem is to add class attributes as
default values for instance members initialised in `__init__`. Note that if
you are only setting default attributes in `__init__` then providing them via
class attributes (shared between instances of course) is faster too. e.g.

.. code-block:: python

    class Something:
        a = 33

This brings up another issue. It is relatively common to provide a default
value of `None` for members that will later be an object of a different type.
`None` would be useless as a spec because it wouldn't let you access *any*
attributes or methods on it. As `None` is *never* going to be useful as a
spec, and probably indicates a member that will normally of some other type,
`autospec` doesn't use a spec for members that are set to `None`. These will
just be ordinary mocks (well - `MagicMocks`):

    >>> class Something:
    ...     member = None
    ...
    >>> mock = create_autospec(Something)
    >>> mock.member.foo.bar.baz()
    <MagicMock name='mock.member.foo.bar.baz()' id='...'>

If modifying your production classes to add defaults isn't to your liking
then there are more options. One of these is simply to use an instance as the
spec rather than the class. The other is to create a subclass of the
production class and add the defaults to the subclass without affecting the
production class. Both of these require you to use an alternative object as
the spec. Thankfully `patch` supports this - you can simply pass the
alternative object as the `autospec` argument:

    >>> class Something:
    ...   def __init__(self):
    ...     self.a = 33
    ...
    >>> class SomethingForTest(Something):
    ...   a = 33
    ...
    >>> p = patch('__main__.Something', autospec=SomethingForTest)
    >>> mock = p.start()
    >>> mock.a
    <NonCallableMagicMock name='Something.a' spec='int' id='...'>


.. [#] This only applies to classes or already instantiated objects. Calling
   a mocked class to create a mock instance *does not* create a real instance.
   It is only attribute lookups - along with calls to `dir` - that are done.

