==================
 Patch Decorators
==================


.. currentmodule:: mock

.. testsetup::

    class SomeClass(object):
        static_method = None
        class_method = None
        attribute = None

    sys.modules['package'] = package = Mock(name='package')
    sys.modules['package.module'] = package.module

    class TestCase(unittest2.TestCase):
        def run(self):
            result = unittest2.TestResult()
            super(unittest2.TestCase, self).run(result)
            assert result.wasSuccessful()

.. testcleanup::

    patch.TEST_PREFIX = 'test'


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

.. doctest::

    >>> @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:

.. doctest::

    >>> class Class(object):
    ...     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.

.. doctest::

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

.. doctest::

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

.. doctest::

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

.. doctest::

    >>> 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 `**`:

.. doctest::

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

.. doctest::

    >>> @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.

.. doctest::

    >>> from mock import patch
    >>> 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:

.. doctest::

    >>> 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__`.

.. doctest::

    >>> class Container(object):
    ...     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.

.. doctest::

    >>> 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`:

.. doctest::

    >>> @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:

.. doctest::

    >>> 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`.

.. doctest::

    >>> 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`:

.. doctest::

    >>> 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. `unittest2
    <http://pypi.python.org/pypi/unittest2>`_ cleanup functions make this
    easier.

    .. doctest::

        >>> 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
        ...
        >>> MyTest('test_something').run()

    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
`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`:

.. doctest::

    >>> patch.TEST_PREFIX = 'foo'
    >>> value = 3
    >>>
    >>> @patch('__main__.value', 'not three')
    ... class Thing(object):
    ...     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:

.. doctest::

    >>> @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.

Like all context-managers patches can be nested using contextlib's nested
function; *every* patching will appear in the tuple after "as":

.. doctest::

    >>> from contextlib import nested
    >>> with nested(
    ...         patch('package.module.ClassName1'),
    ...         patch('package.module.ClassName2')
    ...     ) as (MockClass1, MockClass2):
    ...     assert package.module.ClassName1 is MockClass1
    ...     assert package.module.ClassName2 is MockClass2
    ...


.. _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
======================================

Since version 0.6.0 both patch_ and patch.object_ have been able to correctly
patch and restore descriptors: class methods, static methods and properties.
You should patch these on the *class* rather than an instance.

Since version 0.7.0 patch_ and patch.object_ work correctly 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>`_.

.. note::

    In django `import settings` and `from django.conf import settings`
    return different objects. If you are using libraries / apps that do both you
    may have to patch both. Grrr...
