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()