python/mock-1.0.0/html/_sources/mocksignature.txt

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/python/mock-1.0.0/html/_sources/mocksignature.txt	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,262 @@
     1.4 +mocksignature
     1.5 +=============
     1.6 +
     1.7 +.. currentmodule:: mock
     1.8 +
     1.9 +.. note::
    1.10 +
    1.11 +    :ref:`auto-speccing`, added in mock 0.8, is a more advanced version of
    1.12 +    `mocksignature` and can be used for many of the same use cases.
    1.13 +
    1.14 +A problem with using mock objects to replace real objects in your tests is that
    1.15 +:class:`Mock` can be *too* flexible. Your code can treat the mock objects in
    1.16 +any way and you have to manually check that they were called correctly. If your
    1.17 +code calls functions or methods with the wrong number of arguments then mocks
    1.18 +don't complain.
    1.19 +
    1.20 +The solution to this is `mocksignature`, which creates functions with the
    1.21 +same signature as the original, but delegating to a mock. You can interrogate
    1.22 +the mock in the usual way to check it has been called with the *right*
    1.23 +arguments, but if it is called with the wrong number of arguments it will
    1.24 +raise a `TypeError` in the same way your production code would.
    1.25 +
    1.26 +Another advantage is that your mocked objects are real functions, which can
    1.27 +be useful when your code uses
    1.28 +`inspect <http://docs.python.org/library/inspect.html>`_ or depends on
    1.29 +functions being function objects.
    1.30 +
    1.31 +.. function:: mocksignature(func, mock=None, skipfirst=False)
    1.32 +
    1.33 +    Create a new function with the same signature as `func` that delegates
    1.34 +    to `mock`. If `skipfirst` is True the first argument is skipped, useful
    1.35 +    for methods where `self` needs to be omitted from the new function.
    1.36 +
    1.37 +    If you don't pass in a `mock` then one will be created for you.
    1.38 +
    1.39 +    Functions returned by `mocksignature` have many of the same attributes
    1.40 +    and assert methods as a mock object.
    1.41 +
    1.42 +    The mock is set as the `mock` attribute of the returned function for easy
    1.43 +    access.
    1.44 +
    1.45 +    `mocksignature` can also be used with classes. It copies the signature of
    1.46 +    the `__init__` method.
    1.47 +
    1.48 +    When used with callable objects (instances) it copies the signature of the
    1.49 +    `__call__` method.
    1.50 +
    1.51 +`mocksignature` will work out if it is mocking the signature of a method on
    1.52 +an instance or a method on a class and do the "right thing" with the `self`
    1.53 +argument in both cases.
    1.54 +
    1.55 +Because of a limitation in the way that arguments are collected by functions
    1.56 +created by `mocksignature` they are *always* passed as positional arguments
    1.57 +(including defaults) and not keyword arguments.
    1.58 +
    1.59 +
    1.60 +mocksignature api
    1.61 +-----------------
    1.62 +
    1.63 +Although the objects returned by `mocksignature` api are real function objects,
    1.64 +they have much of the same api as the :class:`Mock` class. This includes the
    1.65 +assert methods:
    1.66 +
    1.67 +.. doctest::
    1.68 +
    1.69 +    >>> def func(a, b, c):
    1.70 +    ...     pass
    1.71 +    ...
    1.72 +    >>> func2 = mocksignature(func)
    1.73 +    >>> func2.called
    1.74 +    False
    1.75 +    >>> func2.return_value = 3
    1.76 +    >>> func2(1, 2, 3)
    1.77 +    3
    1.78 +    >>> func2.called
    1.79 +    True
    1.80 +    >>> func2.assert_called_once_with(1, 2, 3)
    1.81 +    >>> func2.assert_called_with(1, 2, 4)
    1.82 +    Traceback (most recent call last):
    1.83 +      ...
    1.84 +    AssertionError: Expected call: mock(1, 2, 4)
    1.85 +    Actual call: mock(1, 2, 3)
    1.86 +    >>> func2.call_count
    1.87 +    1
    1.88 +    >>> func2.side_effect = IndexError
    1.89 +    >>> func2(4, 5, 6)
    1.90 +    Traceback (most recent call last):
    1.91 +      ...
    1.92 +    IndexError
    1.93 +
    1.94 +The mock object that is being delegated to is available as the `mock` attribute
    1.95 +of the function created by `mocksignature`.
    1.96 +
    1.97 +.. doctest::
    1.98 +
    1.99 +    >>> func2.mock.mock_calls
   1.100 +    [call(1, 2, 3), call(4, 5, 6)]
   1.101 +
   1.102 +The methods and attributes available on functions returned by `mocksignature`
   1.103 +are:
   1.104 +
   1.105 +    :meth:`~Mock.assert_any_call`, :meth:`~Mock.assert_called_once_with`,
   1.106 +    :meth:`~Mock.assert_called_with`, :meth:`~Mock.assert_has_calls`,
   1.107 +    :attr:`~Mock.call_args`, :attr:`~Mock.call_args_list`,
   1.108 +    :attr:`~Mock.call_count`, :attr:`~Mock.called`,
   1.109 +    :attr:`~Mock.method_calls`, `mock`, :attr:`~Mock.mock_calls`,
   1.110 +    :meth:`~Mock.reset_mock`, :attr:`~Mock.return_value`, and
   1.111 +    :attr:`~Mock.side_effect`.
   1.112 +
   1.113 +
   1.114 +Example use
   1.115 +-----------
   1.116 +
   1.117 +Basic use
   1.118 +~~~~~~~~~
   1.119 +
   1.120 +.. doctest::
   1.121 +
   1.122 +    >>> def function(a, b, c=None):
   1.123 +    ...     pass
   1.124 +    ...
   1.125 +    >>> mock = Mock()
   1.126 +    >>> function = mocksignature(function, mock)
   1.127 +    >>> function()
   1.128 +    Traceback (most recent call last):
   1.129 +      ...
   1.130 +    TypeError: <lambda>() takes at least 2 arguments (0 given)
   1.131 +    >>> function.return_value = 'some value'
   1.132 +    >>> function(1, 2, 'foo')
   1.133 +    'some value'
   1.134 +    >>> function.assert_called_with(1, 2, 'foo')
   1.135 +
   1.136 +
   1.137 +Keyword arguments
   1.138 +~~~~~~~~~~~~~~~~~
   1.139 +
   1.140 +Note that arguments to functions created by `mocksignature` are always passed
   1.141 +in to the underlying mock by position even when called with keywords:
   1.142 +
   1.143 +.. doctest::
   1.144 +
   1.145 +    >>> def function(a, b, c=None):
   1.146 +    ...     pass
   1.147 +    ...
   1.148 +    >>> function = mocksignature(function)
   1.149 +    >>> function.return_value = None
   1.150 +    >>> function(1, 2)
   1.151 +    >>> function.assert_called_with(1, 2, None)
   1.152 +
   1.153 +
   1.154 +Mocking methods and self
   1.155 +~~~~~~~~~~~~~~~~~~~~~~~~
   1.156 +
   1.157 +When you use `mocksignature` to replace a method on a class then `self`
   1.158 +will be included in the method signature - and you will need to include
   1.159 +the instance when you do your asserts.
   1.160 +
   1.161 +As a curious factor of the way Python (2) wraps methods fetched from a class,
   1.162 +we can *get* the `return_value` from a function set on a class, but we can't
   1.163 +set it. We have to do this through the exposed `mock` attribute instead:
   1.164 +
   1.165 +.. doctest::
   1.166 +
   1.167 +    >>> class SomeClass(object):
   1.168 +    ...     def method(self, a, b, c=None):
   1.169 +    ...         pass
   1.170 +    ...
   1.171 +    >>> SomeClass.method = mocksignature(SomeClass.method)
   1.172 +    >>> SomeClass.method.mock.return_value = None
   1.173 +    >>> instance = SomeClass()
   1.174 +    >>> instance.method()
   1.175 +    Traceback (most recent call last):
   1.176 +      ...
   1.177 +    TypeError: <lambda>() takes at least 4 arguments (1 given)
   1.178 +    >>> instance.method(1, 2, 3)
   1.179 +    >>> instance.method.assert_called_with(instance, 1, 2, 3)
   1.180 +
   1.181 +When you use `mocksignature` on instance methods `self` isn't included (and we
   1.182 +can set the `return_value` etc directly):
   1.183 +
   1.184 +.. doctest::
   1.185 +
   1.186 +    >>> class SomeClass(object):
   1.187 +    ...     def method(self, a, b, c=None):
   1.188 +    ...         pass
   1.189 +    ...
   1.190 +    >>> instance = SomeClass()
   1.191 +    >>> instance.method = mocksignature(instance.method)
   1.192 +    >>> instance.method.return_value = None
   1.193 +    >>> instance.method(1, 2, 3)
   1.194 +    >>> instance.method.assert_called_with(1, 2, 3)
   1.195 +
   1.196 +
   1.197 +mocksignature with classes
   1.198 +~~~~~~~~~~~~~~~~~~~~~~~~~~
   1.199 +
   1.200 +When used with a class `mocksignature` copies the signature of the `__init__`
   1.201 +method.
   1.202 +
   1.203 +.. doctest::
   1.204 +
   1.205 +    >>> class Something(object):
   1.206 +    ...     def __init__(self, foo, bar):
   1.207 +    ...         pass
   1.208 +    ...
   1.209 +    >>> MockSomething = mocksignature(Something)
   1.210 +    >>> instance = MockSomething(10, 9)
   1.211 +    >>> assert instance is MockSomething.return_value
   1.212 +    >>> MockSomething.assert_called_with(10, 9)
   1.213 +    >>> MockSomething()
   1.214 +    Traceback (most recent call last):
   1.215 +      ...
   1.216 +    TypeError: <lambda>() takes at least 2 arguments (0 given)
   1.217 +
   1.218 +Because the object returned by `mocksignature` is a function rather than a
   1.219 +`Mock` you lose the other capabilities of `Mock`, like dynamic attribute
   1.220 +creation.
   1.221 +
   1.222 +
   1.223 +mocksignature with callable objects
   1.224 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1.225 +
   1.226 +When used with a callable object `mocksignature` copies the signature of the
   1.227 +`__call__` method.
   1.228 +
   1.229 +.. doctest::
   1.230 +
   1.231 +    >>> class Something(object):
   1.232 +    ...     def __call__(self, spam, eggs):
   1.233 +    ...         pass
   1.234 +    ...
   1.235 +    >>> something = Something()
   1.236 +    >>> mock_something = mocksignature(something)
   1.237 +    >>> result = mock_something(10, 9)
   1.238 +    >>> mock_something.assert_called_with(10, 9)
   1.239 +    >>> mock_something()
   1.240 +    Traceback (most recent call last):
   1.241 +      ...
   1.242 +    TypeError: <lambda>() takes at least 2 arguments (0 given)
   1.243 +
   1.244 +
   1.245 +mocksignature argument to patch
   1.246 +-------------------------------
   1.247 +
   1.248 +`mocksignature` is available as a keyword argument to :func:`patch` or
   1.249 +:func:`patch.object`. It can be used with functions / methods / classes and
   1.250 +callable objects.
   1.251 +
   1.252 +.. doctest::
   1.253 +
   1.254 +    >>> class SomeClass(object):
   1.255 +    ...     def method(self, a, b, c=None):
   1.256 +    ...         pass
   1.257 +    ...
   1.258 +    >>> @patch.object(SomeClass, 'method', mocksignature=True)
   1.259 +    ... def test(mock_method):
   1.260 +    ...     instance = SomeClass()
   1.261 +    ...     mock_method.return_value = None
   1.262 +    ...     instance.method(1, 2)
   1.263 +    ...     mock_method.assert_called_with(instance, 1, 2, None)
   1.264 +    ...
   1.265 +    >>> test()

mercurial