зеркало из https://github.com/mozilla/gecko-dev.git
637 строки
22 KiB
Plaintext
637 строки
22 KiB
Plaintext
==================
|
|
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...
|