python/mock-1.0.0/docs/helpers.txt

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 =========
michael@0 2 Helpers
michael@0 3 =========
michael@0 4
michael@0 5 .. currentmodule:: mock
michael@0 6
michael@0 7 .. testsetup::
michael@0 8
michael@0 9 mock.FILTER_DIR = True
michael@0 10 from pprint import pprint as pp
michael@0 11 original_dir = dir
michael@0 12 def dir(obj):
michael@0 13 print pp(original_dir(obj))
michael@0 14
michael@0 15 import urllib2
michael@0 16 __main__.urllib2 = urllib2
michael@0 17
michael@0 18 .. testcleanup::
michael@0 19
michael@0 20 dir = original_dir
michael@0 21 mock.FILTER_DIR = True
michael@0 22
michael@0 23
michael@0 24
michael@0 25 call
michael@0 26 ====
michael@0 27
michael@0 28 .. function:: call(*args, **kwargs)
michael@0 29
michael@0 30 `call` is a helper object for making simpler assertions, for comparing
michael@0 31 with :attr:`~Mock.call_args`, :attr:`~Mock.call_args_list`,
michael@0 32 :attr:`~Mock.mock_calls` and :attr: `~Mock.method_calls`. `call` can also be
michael@0 33 used with :meth:`~Mock.assert_has_calls`.
michael@0 34
michael@0 35 .. doctest::
michael@0 36
michael@0 37 >>> m = MagicMock(return_value=None)
michael@0 38 >>> m(1, 2, a='foo', b='bar')
michael@0 39 >>> m()
michael@0 40 >>> m.call_args_list == [call(1, 2, a='foo', b='bar'), call()]
michael@0 41 True
michael@0 42
michael@0 43 .. method:: call.call_list()
michael@0 44
michael@0 45 For a call object that represents multiple calls, `call_list`
michael@0 46 returns a list of all the intermediate calls as well as the
michael@0 47 final call.
michael@0 48
michael@0 49 `call_list` is particularly useful for making assertions on "chained calls". A
michael@0 50 chained call is multiple calls on a single line of code. This results in
michael@0 51 multiple entries in :attr:`~Mock.mock_calls` on a mock. Manually constructing
michael@0 52 the sequence of calls can be tedious.
michael@0 53
michael@0 54 :meth:`~call.call_list` can construct the sequence of calls from the same
michael@0 55 chained call:
michael@0 56
michael@0 57 .. doctest::
michael@0 58
michael@0 59 >>> m = MagicMock()
michael@0 60 >>> m(1).method(arg='foo').other('bar')(2.0)
michael@0 61 <MagicMock name='mock().method().other()()' id='...'>
michael@0 62 >>> kall = call(1).method(arg='foo').other('bar')(2.0)
michael@0 63 >>> kall.call_list()
michael@0 64 [call(1),
michael@0 65 call().method(arg='foo'),
michael@0 66 call().method().other('bar'),
michael@0 67 call().method().other()(2.0)]
michael@0 68 >>> m.mock_calls == kall.call_list()
michael@0 69 True
michael@0 70
michael@0 71 .. _calls-as-tuples:
michael@0 72
michael@0 73 A `call` object is either a tuple of (positional args, keyword args) or
michael@0 74 (name, positional args, keyword args) depending on how it was constructed. When
michael@0 75 you construct them yourself this isn't particularly interesting, but the `call`
michael@0 76 objects that are in the :attr:`Mock.call_args`, :attr:`Mock.call_args_list` and
michael@0 77 :attr:`Mock.mock_calls` attributes can be introspected to get at the individual
michael@0 78 arguments they contain.
michael@0 79
michael@0 80 The `call` objects in :attr:`Mock.call_args` and :attr:`Mock.call_args_list`
michael@0 81 are two-tuples of (positional args, keyword args) whereas the `call` objects
michael@0 82 in :attr:`Mock.mock_calls`, along with ones you construct yourself, are
michael@0 83 three-tuples of (name, positional args, keyword args).
michael@0 84
michael@0 85 You can use their "tupleness" to pull out the individual arguments for more
michael@0 86 complex introspection and assertions. The positional arguments are a tuple
michael@0 87 (an empty tuple if there are no positional arguments) and the keyword
michael@0 88 arguments are a dictionary:
michael@0 89
michael@0 90 .. doctest::
michael@0 91
michael@0 92 >>> m = MagicMock(return_value=None)
michael@0 93 >>> m(1, 2, 3, arg='one', arg2='two')
michael@0 94 >>> kall = m.call_args
michael@0 95 >>> args, kwargs = kall
michael@0 96 >>> args
michael@0 97 (1, 2, 3)
michael@0 98 >>> kwargs
michael@0 99 {'arg2': 'two', 'arg': 'one'}
michael@0 100 >>> args is kall[0]
michael@0 101 True
michael@0 102 >>> kwargs is kall[1]
michael@0 103 True
michael@0 104
michael@0 105 >>> m = MagicMock()
michael@0 106 >>> m.foo(4, 5, 6, arg='two', arg2='three')
michael@0 107 <MagicMock name='mock.foo()' id='...'>
michael@0 108 >>> kall = m.mock_calls[0]
michael@0 109 >>> name, args, kwargs = kall
michael@0 110 >>> name
michael@0 111 'foo'
michael@0 112 >>> args
michael@0 113 (4, 5, 6)
michael@0 114 >>> kwargs
michael@0 115 {'arg2': 'three', 'arg': 'two'}
michael@0 116 >>> name is m.mock_calls[0][0]
michael@0 117 True
michael@0 118
michael@0 119
michael@0 120 create_autospec
michael@0 121 ===============
michael@0 122
michael@0 123 .. function:: create_autospec(spec, spec_set=False, instance=False, **kwargs)
michael@0 124
michael@0 125 Create a mock object using another object as a spec. Attributes on the
michael@0 126 mock will use the corresponding attribute on the `spec` object as their
michael@0 127 spec.
michael@0 128
michael@0 129 Functions or methods being mocked will have their arguments checked to
michael@0 130 ensure that they are called with the correct signature.
michael@0 131
michael@0 132 If `spec_set` is `True` then attempting to set attributes that don't exist
michael@0 133 on the spec object will raise an `AttributeError`.
michael@0 134
michael@0 135 If a class is used as a spec then the return value of the mock (the
michael@0 136 instance of the class) will have the same spec. You can use a class as the
michael@0 137 spec for an instance object by passing `instance=True`. The returned mock
michael@0 138 will only be callable if instances of the mock are callable.
michael@0 139
michael@0 140 `create_autospec` also takes arbitrary keyword arguments that are passed to
michael@0 141 the constructor of the created mock.
michael@0 142
michael@0 143 See :ref:`auto-speccing` for examples of how to use auto-speccing with
michael@0 144 `create_autospec` and the `autospec` argument to :func:`patch`.
michael@0 145
michael@0 146
michael@0 147 ANY
michael@0 148 ===
michael@0 149
michael@0 150 .. data:: ANY
michael@0 151
michael@0 152 Sometimes you may need to make assertions about *some* of the arguments in a
michael@0 153 call to mock, but either not care about some of the arguments or want to pull
michael@0 154 them individually out of :attr:`~Mock.call_args` and make more complex
michael@0 155 assertions on them.
michael@0 156
michael@0 157 To ignore certain arguments you can pass in objects that compare equal to
michael@0 158 *everything*. Calls to :meth:`~Mock.assert_called_with` and
michael@0 159 :meth:`~Mock.assert_called_once_with` will then succeed no matter what was
michael@0 160 passed in.
michael@0 161
michael@0 162 .. doctest::
michael@0 163
michael@0 164 >>> mock = Mock(return_value=None)
michael@0 165 >>> mock('foo', bar=object())
michael@0 166 >>> mock.assert_called_once_with('foo', bar=ANY)
michael@0 167
michael@0 168 `ANY` can also be used in comparisons with call lists like
michael@0 169 :attr:`~Mock.mock_calls`:
michael@0 170
michael@0 171 .. doctest::
michael@0 172
michael@0 173 >>> m = MagicMock(return_value=None)
michael@0 174 >>> m(1)
michael@0 175 >>> m(1, 2)
michael@0 176 >>> m(object())
michael@0 177 >>> m.mock_calls == [call(1), call(1, 2), ANY]
michael@0 178 True
michael@0 179
michael@0 180
michael@0 181
michael@0 182 FILTER_DIR
michael@0 183 ==========
michael@0 184
michael@0 185 .. data:: FILTER_DIR
michael@0 186
michael@0 187 `FILTER_DIR` is a module level variable that controls the way mock objects
michael@0 188 respond to `dir` (only for Python 2.6 or more recent). The default is `True`,
michael@0 189 which uses the filtering described below, to only show useful members. If you
michael@0 190 dislike this filtering, or need to switch it off for diagnostic purposes, then
michael@0 191 set `mock.FILTER_DIR = False`.
michael@0 192
michael@0 193 With filtering on, `dir(some_mock)` shows only useful attributes and will
michael@0 194 include any dynamically created attributes that wouldn't normally be shown.
michael@0 195 If the mock was created with a `spec` (or `autospec` of course) then all the
michael@0 196 attributes from the original are shown, even if they haven't been accessed
michael@0 197 yet:
michael@0 198
michael@0 199 .. doctest::
michael@0 200
michael@0 201 >>> dir(Mock())
michael@0 202 ['assert_any_call',
michael@0 203 'assert_called_once_with',
michael@0 204 'assert_called_with',
michael@0 205 'assert_has_calls',
michael@0 206 'attach_mock',
michael@0 207 ...
michael@0 208 >>> import urllib2
michael@0 209 >>> dir(Mock(spec=urllib2))
michael@0 210 ['AbstractBasicAuthHandler',
michael@0 211 'AbstractDigestAuthHandler',
michael@0 212 'AbstractHTTPHandler',
michael@0 213 'BaseHandler',
michael@0 214 ...
michael@0 215
michael@0 216 Many of the not-very-useful (private to `Mock` rather than the thing being
michael@0 217 mocked) underscore and double underscore prefixed attributes have been
michael@0 218 filtered from the result of calling `dir` on a `Mock`. If you dislike this
michael@0 219 behaviour you can switch it off by setting the module level switch
michael@0 220 `FILTER_DIR`:
michael@0 221
michael@0 222 .. doctest::
michael@0 223
michael@0 224 >>> import mock
michael@0 225 >>> mock.FILTER_DIR = False
michael@0 226 >>> dir(mock.Mock())
michael@0 227 ['_NonCallableMock__get_return_value',
michael@0 228 '_NonCallableMock__get_side_effect',
michael@0 229 '_NonCallableMock__return_value_doc',
michael@0 230 '_NonCallableMock__set_return_value',
michael@0 231 '_NonCallableMock__set_side_effect',
michael@0 232 '__call__',
michael@0 233 '__class__',
michael@0 234 ...
michael@0 235
michael@0 236 Alternatively you can just use `vars(my_mock)` (instance members) and
michael@0 237 `dir(type(my_mock))` (type members) to bypass the filtering irrespective of
michael@0 238 `mock.FILTER_DIR`.
michael@0 239
michael@0 240
michael@0 241 mock_open
michael@0 242 =========
michael@0 243
michael@0 244 .. function:: mock_open(mock=None, read_data=None)
michael@0 245
michael@0 246 A helper function to create a mock to replace the use of `open`. It works
michael@0 247 for `open` called directly or used as a context manager.
michael@0 248
michael@0 249 The `mock` argument is the mock object to configure. If `None` (the
michael@0 250 default) then a `MagicMock` will be created for you, with the API limited
michael@0 251 to methods or attributes available on standard file handles.
michael@0 252
michael@0 253 `read_data` is a string for the `read` method of the file handle to return.
michael@0 254 This is an empty string by default.
michael@0 255
michael@0 256 Using `open` as a context manager is a great way to ensure your file handles
michael@0 257 are closed properly and is becoming common::
michael@0 258
michael@0 259 with open('/some/path', 'w') as f:
michael@0 260 f.write('something')
michael@0 261
michael@0 262 The issue is that even if you mock out the call to `open` it is the
michael@0 263 *returned object* that is used as a context manager (and has `__enter__` and
michael@0 264 `__exit__` called).
michael@0 265
michael@0 266 Mocking context managers with a :class:`MagicMock` is common enough and fiddly
michael@0 267 enough that a helper function is useful.
michael@0 268
michael@0 269 .. doctest::
michael@0 270
michael@0 271 >>> from mock import mock_open
michael@0 272 >>> m = mock_open()
michael@0 273 >>> with patch('__main__.open', m, create=True):
michael@0 274 ... with open('foo', 'w') as h:
michael@0 275 ... h.write('some stuff')
michael@0 276 ...
michael@0 277 >>> m.mock_calls
michael@0 278 [call('foo', 'w'),
michael@0 279 call().__enter__(),
michael@0 280 call().write('some stuff'),
michael@0 281 call().__exit__(None, None, None)]
michael@0 282 >>> m.assert_called_once_with('foo', 'w')
michael@0 283 >>> handle = m()
michael@0 284 >>> handle.write.assert_called_once_with('some stuff')
michael@0 285
michael@0 286 And for reading files:
michael@0 287
michael@0 288 .. doctest::
michael@0 289
michael@0 290 >>> with patch('__main__.open', mock_open(read_data='bibble'), create=True) as m:
michael@0 291 ... with open('foo') as h:
michael@0 292 ... result = h.read()
michael@0 293 ...
michael@0 294 >>> m.assert_called_once_with('foo')
michael@0 295 >>> assert result == 'bibble'
michael@0 296
michael@0 297
michael@0 298 .. _auto-speccing:
michael@0 299
michael@0 300 Autospeccing
michael@0 301 ============
michael@0 302
michael@0 303 Autospeccing is based on the existing `spec` feature of mock. It limits the
michael@0 304 api of mocks to the api of an original object (the spec), but it is recursive
michael@0 305 (implemented lazily) so that attributes of mocks only have the same api as
michael@0 306 the attributes of the spec. In addition mocked functions / methods have the
michael@0 307 same call signature as the original so they raise a `TypeError` if they are
michael@0 308 called incorrectly.
michael@0 309
michael@0 310 Before I explain how auto-speccing works, here's why it is needed.
michael@0 311
michael@0 312 `Mock` is a very powerful and flexible object, but it suffers from two flaws
michael@0 313 when used to mock out objects from a system under test. One of these flaws is
michael@0 314 specific to the `Mock` api and the other is a more general problem with using
michael@0 315 mock objects.
michael@0 316
michael@0 317 First the problem specific to `Mock`. `Mock` has two assert methods that are
michael@0 318 extremely handy: :meth:`~Mock.assert_called_with` and
michael@0 319 :meth:`~Mock.assert_called_once_with`.
michael@0 320
michael@0 321 .. doctest::
michael@0 322
michael@0 323 >>> mock = Mock(name='Thing', return_value=None)
michael@0 324 >>> mock(1, 2, 3)
michael@0 325 >>> mock.assert_called_once_with(1, 2, 3)
michael@0 326 >>> mock(1, 2, 3)
michael@0 327 >>> mock.assert_called_once_with(1, 2, 3)
michael@0 328 Traceback (most recent call last):
michael@0 329 ...
michael@0 330 AssertionError: Expected to be called once. Called 2 times.
michael@0 331
michael@0 332 Because mocks auto-create attributes on demand, and allow you to call them
michael@0 333 with arbitrary arguments, if you misspell one of these assert methods then
michael@0 334 your assertion is gone:
michael@0 335
michael@0 336 .. code-block:: pycon
michael@0 337
michael@0 338 >>> mock = Mock(name='Thing', return_value=None)
michael@0 339 >>> mock(1, 2, 3)
michael@0 340 >>> mock.assret_called_once_with(4, 5, 6)
michael@0 341
michael@0 342 Your tests can pass silently and incorrectly because of the typo.
michael@0 343
michael@0 344 The second issue is more general to mocking. If you refactor some of your
michael@0 345 code, rename members and so on, any tests for code that is still using the
michael@0 346 *old api* but uses mocks instead of the real objects will still pass. This
michael@0 347 means your tests can all pass even though your code is broken.
michael@0 348
michael@0 349 Note that this is another reason why you need integration tests as well as
michael@0 350 unit tests. Testing everything in isolation is all fine and dandy, but if you
michael@0 351 don't test how your units are "wired together" there is still lots of room
michael@0 352 for bugs that tests might have caught.
michael@0 353
michael@0 354 `mock` already provides a feature to help with this, called speccing. If you
michael@0 355 use a class or instance as the `spec` for a mock then you can only access
michael@0 356 attributes on the mock that exist on the real class:
michael@0 357
michael@0 358 .. doctest::
michael@0 359
michael@0 360 >>> import urllib2
michael@0 361 >>> mock = Mock(spec=urllib2.Request)
michael@0 362 >>> mock.assret_called_with
michael@0 363 Traceback (most recent call last):
michael@0 364 ...
michael@0 365 AttributeError: Mock object has no attribute 'assret_called_with'
michael@0 366
michael@0 367 The spec only applies to the mock itself, so we still have the same issue
michael@0 368 with any methods on the mock:
michael@0 369
michael@0 370 .. code-block:: pycon
michael@0 371
michael@0 372 >>> mock.has_data()
michael@0 373 <mock.Mock object at 0x...>
michael@0 374 >>> mock.has_data.assret_called_with()
michael@0 375
michael@0 376 Auto-speccing solves this problem. You can either pass `autospec=True` to
michael@0 377 `patch` / `patch.object` or use the `create_autospec` function to create a
michael@0 378 mock with a spec. If you use the `autospec=True` argument to `patch` then the
michael@0 379 object that is being replaced will be used as the spec object. Because the
michael@0 380 speccing is done "lazily" (the spec is created as attributes on the mock are
michael@0 381 accessed) you can use it with very complex or deeply nested objects (like
michael@0 382 modules that import modules that import modules) without a big performance
michael@0 383 hit.
michael@0 384
michael@0 385 Here's an example of it in use:
michael@0 386
michael@0 387 .. doctest::
michael@0 388
michael@0 389 >>> import urllib2
michael@0 390 >>> patcher = patch('__main__.urllib2', autospec=True)
michael@0 391 >>> mock_urllib2 = patcher.start()
michael@0 392 >>> urllib2 is mock_urllib2
michael@0 393 True
michael@0 394 >>> urllib2.Request
michael@0 395 <MagicMock name='urllib2.Request' spec='Request' id='...'>
michael@0 396
michael@0 397 You can see that `urllib2.Request` has a spec. `urllib2.Request` takes two
michael@0 398 arguments in the constructor (one of which is `self`). Here's what happens if
michael@0 399 we try to call it incorrectly:
michael@0 400
michael@0 401 .. doctest::
michael@0 402
michael@0 403 >>> req = urllib2.Request()
michael@0 404 Traceback (most recent call last):
michael@0 405 ...
michael@0 406 TypeError: <lambda>() takes at least 2 arguments (1 given)
michael@0 407
michael@0 408 The spec also applies to instantiated classes (i.e. the return value of
michael@0 409 specced mocks):
michael@0 410
michael@0 411 .. doctest::
michael@0 412
michael@0 413 >>> req = urllib2.Request('foo')
michael@0 414 >>> req
michael@0 415 <NonCallableMagicMock name='urllib2.Request()' spec='Request' id='...'>
michael@0 416
michael@0 417 `Request` objects are not callable, so the return value of instantiating our
michael@0 418 mocked out `urllib2.Request` is a non-callable mock. With the spec in place
michael@0 419 any typos in our asserts will raise the correct error:
michael@0 420
michael@0 421 .. doctest::
michael@0 422
michael@0 423 >>> req.add_header('spam', 'eggs')
michael@0 424 <MagicMock name='urllib2.Request().add_header()' id='...'>
michael@0 425 >>> req.add_header.assret_called_with
michael@0 426 Traceback (most recent call last):
michael@0 427 ...
michael@0 428 AttributeError: Mock object has no attribute 'assret_called_with'
michael@0 429 >>> req.add_header.assert_called_with('spam', 'eggs')
michael@0 430
michael@0 431 In many cases you will just be able to add `autospec=True` to your existing
michael@0 432 `patch` calls and then be protected against bugs due to typos and api
michael@0 433 changes.
michael@0 434
michael@0 435 As well as using `autospec` through `patch` there is a
michael@0 436 :func:`create_autospec` for creating autospecced mocks directly:
michael@0 437
michael@0 438 .. doctest::
michael@0 439
michael@0 440 >>> import urllib2
michael@0 441 >>> mock_urllib2 = create_autospec(urllib2)
michael@0 442 >>> mock_urllib2.Request('foo', 'bar')
michael@0 443 <NonCallableMagicMock name='mock.Request()' spec='Request' id='...'>
michael@0 444
michael@0 445 This isn't without caveats and limitations however, which is why it is not
michael@0 446 the default behaviour. In order to know what attributes are available on the
michael@0 447 spec object, autospec has to introspect (access attributes) the spec. As you
michael@0 448 traverse attributes on the mock a corresponding traversal of the original
michael@0 449 object is happening under the hood. If any of your specced objects have
michael@0 450 properties or descriptors that can trigger code execution then you may not be
michael@0 451 able to use autospec. On the other hand it is much better to design your
michael@0 452 objects so that introspection is safe [#]_.
michael@0 453
michael@0 454 A more serious problem is that it is common for instance attributes to be
michael@0 455 created in the `__init__` method and not to exist on the class at all.
michael@0 456 `autospec` can't know about any dynamically created attributes and restricts
michael@0 457 the api to visible attributes.
michael@0 458
michael@0 459 .. doctest::
michael@0 460
michael@0 461 >>> class Something(object):
michael@0 462 ... def __init__(self):
michael@0 463 ... self.a = 33
michael@0 464 ...
michael@0 465 >>> with patch('__main__.Something', autospec=True):
michael@0 466 ... thing = Something()
michael@0 467 ... thing.a
michael@0 468 ...
michael@0 469 Traceback (most recent call last):
michael@0 470 ...
michael@0 471 AttributeError: Mock object has no attribute 'a'
michael@0 472
michael@0 473 There are a few different ways of resolving this problem. The easiest, but
michael@0 474 not necessarily the least annoying, way is to simply set the required
michael@0 475 attributes on the mock after creation. Just because `autospec` doesn't allow
michael@0 476 you to fetch attributes that don't exist on the spec it doesn't prevent you
michael@0 477 setting them:
michael@0 478
michael@0 479 .. doctest::
michael@0 480
michael@0 481 >>> with patch('__main__.Something', autospec=True):
michael@0 482 ... thing = Something()
michael@0 483 ... thing.a = 33
michael@0 484 ...
michael@0 485
michael@0 486 There is a more aggressive version of both `spec` and `autospec` that *does*
michael@0 487 prevent you setting non-existent attributes. This is useful if you want to
michael@0 488 ensure your code only *sets* valid attributes too, but obviously it prevents
michael@0 489 this particular scenario:
michael@0 490
michael@0 491 .. doctest::
michael@0 492
michael@0 493 >>> with patch('__main__.Something', autospec=True, spec_set=True):
michael@0 494 ... thing = Something()
michael@0 495 ... thing.a = 33
michael@0 496 ...
michael@0 497 Traceback (most recent call last):
michael@0 498 ...
michael@0 499 AttributeError: Mock object has no attribute 'a'
michael@0 500
michael@0 501 Probably the best way of solving the problem is to add class attributes as
michael@0 502 default values for instance members initialised in `__init__`. Note that if
michael@0 503 you are only setting default attributes in `__init__` then providing them via
michael@0 504 class attributes (shared between instances of course) is faster too. e.g.
michael@0 505
michael@0 506 .. code-block:: python
michael@0 507
michael@0 508 class Something(object):
michael@0 509 a = 33
michael@0 510
michael@0 511 This brings up another issue. It is relatively common to provide a default
michael@0 512 value of `None` for members that will later be an object of a different type.
michael@0 513 `None` would be useless as a spec because it wouldn't let you access *any*
michael@0 514 attributes or methods on it. As `None` is *never* going to be useful as a
michael@0 515 spec, and probably indicates a member that will normally of some other type,
michael@0 516 `autospec` doesn't use a spec for members that are set to `None`. These will
michael@0 517 just be ordinary mocks (well - `MagicMocks`):
michael@0 518
michael@0 519 .. doctest::
michael@0 520
michael@0 521 >>> class Something(object):
michael@0 522 ... member = None
michael@0 523 ...
michael@0 524 >>> mock = create_autospec(Something)
michael@0 525 >>> mock.member.foo.bar.baz()
michael@0 526 <MagicMock name='mock.member.foo.bar.baz()' id='...'>
michael@0 527
michael@0 528 If modifying your production classes to add defaults isn't to your liking
michael@0 529 then there are more options. One of these is simply to use an instance as the
michael@0 530 spec rather than the class. The other is to create a subclass of the
michael@0 531 production class and add the defaults to the subclass without affecting the
michael@0 532 production class. Both of these require you to use an alternative object as
michael@0 533 the spec. Thankfully `patch` supports this - you can simply pass the
michael@0 534 alternative object as the `autospec` argument:
michael@0 535
michael@0 536 .. doctest::
michael@0 537
michael@0 538 >>> class Something(object):
michael@0 539 ... def __init__(self):
michael@0 540 ... self.a = 33
michael@0 541 ...
michael@0 542 >>> class SomethingForTest(Something):
michael@0 543 ... a = 33
michael@0 544 ...
michael@0 545 >>> p = patch('__main__.Something', autospec=SomethingForTest)
michael@0 546 >>> mock = p.start()
michael@0 547 >>> mock.a
michael@0 548 <NonCallableMagicMock name='Something.a' spec='int' id='...'>
michael@0 549
michael@0 550 .. note::
michael@0 551
michael@0 552 An additional limitation (currently) with `autospec` is that unbound
michael@0 553 methods on mocked classes *don't* take an "explicit self" as the first
michael@0 554 argument - so this usage will fail with `autospec`.
michael@0 555
michael@0 556 .. doctest::
michael@0 557
michael@0 558 >>> class Foo(object):
michael@0 559 ... def foo(self):
michael@0 560 ... pass
michael@0 561 ...
michael@0 562 >>> Foo.foo(Foo())
michael@0 563 >>> MockFoo = create_autospec(Foo)
michael@0 564 >>> MockFoo.foo(MockFoo())
michael@0 565 Traceback (most recent call last):
michael@0 566 ...
michael@0 567 TypeError: <lambda>() takes exactly 1 argument (2 given)
michael@0 568
michael@0 569 The reason is that its very hard to tell the difference between functions,
michael@0 570 unbound methods and staticmethods across Python 2 & 3 and the alternative
michael@0 571 implementations. This restriction may be fixed in future versions.
michael@0 572
michael@0 573
michael@0 574 ------
michael@0 575
michael@0 576 .. [#] This only applies to classes or already instantiated objects. Calling
michael@0 577 a mocked class to create a mock instance *does not* create a real instance.
michael@0 578 It is only attribute lookups - along with calls to `dir` - that are done. A
michael@0 579 way round this problem would have been to use `getattr_static
michael@0 580 <http://docs.python.org/dev/library/inspect.html#inspect.getattr_static>`_,
michael@0 581 which can fetch attributes without triggering code execution. Descriptors
michael@0 582 like `classmethod` and `staticmethod` *need* to be fetched correctly though,
michael@0 583 so that their signatures can be mocked correctly.

mercurial