summaryrefslogtreecommitdiffstats
path: root/Doc/library/unittest.mock-helpers.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/library/unittest.mock-helpers.rst')
-rw-r--r--Doc/library/unittest.mock-helpers.rst537
1 files changed, 0 insertions, 537 deletions
diff --git a/Doc/library/unittest.mock-helpers.rst b/Doc/library/unittest.mock-helpers.rst
deleted file mode 100644
index 6c68a48..0000000
--- a/Doc/library/unittest.mock-helpers.rst
+++ /dev/null
@@ -1,537 +0,0 @@
-:mod:`unittest.mock` --- helpers
-================================
-
-.. module:: unittest.mock
- :synopsis: Mock object library.
-.. moduleauthor:: Michael Foord <michael@python.org>
-.. currentmodule:: unittest.mock
-
-.. versionadded:: 3.3
-
-
-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` method of the file handle to return.
- This 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 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(object):
- ... 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(object):
- 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(object):
- ... 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(object):
- ... 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.