123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- .. currentmodule:: mock
- .. _magic-methods:
- Mocking Magic Methods
- =====================
- .. currentmodule:: mock
- :class:`Mock` supports mocking `magic methods
- <http://www.ironpythoninaction.com/magic-methods.html>`_. 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 [#]_.
- .. doctest::
- >>> 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:
- .. doctest::
- >>> 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 are supported in Python 2 but don't exist in Python 3:
- * ``__unicode__``, ``__long__``, ``__oct__``, ``__hex__`` and ``__nonzero__``
- * ``__truediv__`` and ``__rtruediv__``
- The following methods are supported in Python 3 but don't exist in Python 2:
- * ``__bool__`` and ``__next__``
- 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:
- .. doctest::
- >>> 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
- * ``__nonzero__`` : True
- * ``__oct__`` : '1'
- * ``__hex__`` : '0x1'
- * ``__long__`` : long(1)
- * ``__index__`` : 1
- * ``__hash__`` : default hash for the mock
- * ``__str__`` : default str for the mock
- * ``__unicode__`` : default unicode for the mock
- * ``__sizeof__``: default sizeof for the mock
- For example:
- .. doctest::
- >>> mock = MagicMock()
- >>> int(mock)
- 1
- >>> len(mock)
- 0
- >>> hex(mock)
- '0x1'
- >>> list(mock)
- []
- >>> object() in mock
- False
- The two equality method, `__eq__` and `__ne__`, are special (changed in
- 0.7.2). They do the default equality comparison on identity, using a side
- effect, unless you change their return value to return something else:
- .. doctest::
- >>> MagicMock() == 3
- False
- >>> MagicMock() != 3
- True
- >>> mock = MagicMock()
- >>> mock.__eq__.return_value = True
- >>> mock == 3
- True
- In `0.8` the `__iter__` also gained special handling implemented with a
- side effect. The return value of `MagicMock.__iter__` can be any iterable
- object and isn't required to be an iterator:
- .. doctest::
- >>> 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:
- .. doctest::
- >>> 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:
- * ``__cmp__``
- * ``__getslice__`` and ``__setslice__``
- * ``__coerce__``
- * ``__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.
|