python/mock-1.0.0/docs/getting-started.txt

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 ===========================
michael@0 2 Getting Started with Mock
michael@0 3 ===========================
michael@0 4
michael@0 5 .. _getting-started:
michael@0 6
michael@0 7 .. index:: Getting Started
michael@0 8
michael@0 9 .. testsetup::
michael@0 10
michael@0 11 class SomeClass(object):
michael@0 12 static_method = None
michael@0 13 class_method = None
michael@0 14 attribute = None
michael@0 15
michael@0 16 sys.modules['package'] = package = Mock(name='package')
michael@0 17 sys.modules['package.module'] = module = package.module
michael@0 18 sys.modules['module'] = package.module
michael@0 19
michael@0 20
michael@0 21 Using Mock
michael@0 22 ==========
michael@0 23
michael@0 24 Mock Patching Methods
michael@0 25 ---------------------
michael@0 26
michael@0 27 Common uses for :class:`Mock` objects include:
michael@0 28
michael@0 29 * Patching methods
michael@0 30 * Recording method calls on objects
michael@0 31
michael@0 32 You might want to replace a method on an object to check that
michael@0 33 it is called with the correct arguments by another part of the system:
michael@0 34
michael@0 35 .. doctest::
michael@0 36
michael@0 37 >>> real = SomeClass()
michael@0 38 >>> real.method = MagicMock(name='method')
michael@0 39 >>> real.method(3, 4, 5, key='value')
michael@0 40 <MagicMock name='method()' id='...'>
michael@0 41
michael@0 42 Once our mock has been used (`real.method` in this example) it has methods
michael@0 43 and attributes that allow you to make assertions about how it has been used.
michael@0 44
michael@0 45 .. note::
michael@0 46
michael@0 47 In most of these examples the :class:`Mock` and :class:`MagicMock` classes
michael@0 48 are interchangeable. As the `MagicMock` is the more capable class it makes
michael@0 49 a sensible one to use by default.
michael@0 50
michael@0 51 Once the mock has been called its :attr:`~Mock.called` attribute is set to
michael@0 52 `True`. More importantly we can use the :meth:`~Mock.assert_called_with` or
michael@0 53 :meth:`~Mock.assert_called_once_with` method to check that it was called with
michael@0 54 the correct arguments.
michael@0 55
michael@0 56 This example tests that calling `ProductionClass().method` results in a call to
michael@0 57 the `something` method:
michael@0 58
michael@0 59 .. doctest::
michael@0 60
michael@0 61 >>> from mock import MagicMock
michael@0 62 >>> class ProductionClass(object):
michael@0 63 ... def method(self):
michael@0 64 ... self.something(1, 2, 3)
michael@0 65 ... def something(self, a, b, c):
michael@0 66 ... pass
michael@0 67 ...
michael@0 68 >>> real = ProductionClass()
michael@0 69 >>> real.something = MagicMock()
michael@0 70 >>> real.method()
michael@0 71 >>> real.something.assert_called_once_with(1, 2, 3)
michael@0 72
michael@0 73
michael@0 74
michael@0 75 Mock for Method Calls on an Object
michael@0 76 ----------------------------------
michael@0 77
michael@0 78 In the last example we patched a method directly on an object to check that it
michael@0 79 was called correctly. Another common use case is to pass an object into a
michael@0 80 method (or some part of the system under test) and then check that it is used
michael@0 81 in the correct way.
michael@0 82
michael@0 83 The simple `ProductionClass` below has a `closer` method. If it is called with
michael@0 84 an object then it calls `close` on it.
michael@0 85
michael@0 86 .. doctest::
michael@0 87
michael@0 88 >>> class ProductionClass(object):
michael@0 89 ... def closer(self, something):
michael@0 90 ... something.close()
michael@0 91 ...
michael@0 92
michael@0 93 So to test it we need to pass in an object with a `close` method and check
michael@0 94 that it was called correctly.
michael@0 95
michael@0 96 .. doctest::
michael@0 97
michael@0 98 >>> real = ProductionClass()
michael@0 99 >>> mock = Mock()
michael@0 100 >>> real.closer(mock)
michael@0 101 >>> mock.close.assert_called_with()
michael@0 102
michael@0 103 We don't have to do any work to provide the 'close' method on our mock.
michael@0 104 Accessing close creates it. So, if 'close' hasn't already been called then
michael@0 105 accessing it in the test will create it, but :meth:`~Mock.assert_called_with`
michael@0 106 will raise a failure exception.
michael@0 107
michael@0 108
michael@0 109 Mocking Classes
michael@0 110 ---------------
michael@0 111
michael@0 112 A common use case is to mock out classes instantiated by your code under test.
michael@0 113 When you patch a class, then that class is replaced with a mock. Instances
michael@0 114 are created by *calling the class*. This means you access the "mock instance"
michael@0 115 by looking at the return value of the mocked class.
michael@0 116
michael@0 117 In the example below we have a function `some_function` that instantiates `Foo`
michael@0 118 and calls a method on it. The call to `patch` replaces the class `Foo` with a
michael@0 119 mock. The `Foo` instance is the result of calling the mock, so it is configured
michael@0 120 by modifying the mock :attr:`~Mock.return_value`.
michael@0 121
michael@0 122 .. doctest::
michael@0 123
michael@0 124 >>> def some_function():
michael@0 125 ... instance = module.Foo()
michael@0 126 ... return instance.method()
michael@0 127 ...
michael@0 128 >>> with patch('module.Foo') as mock:
michael@0 129 ... instance = mock.return_value
michael@0 130 ... instance.method.return_value = 'the result'
michael@0 131 ... result = some_function()
michael@0 132 ... assert result == 'the result'
michael@0 133
michael@0 134
michael@0 135 Naming your mocks
michael@0 136 -----------------
michael@0 137
michael@0 138 It can be useful to give your mocks a name. The name is shown in the repr of
michael@0 139 the mock and can be helpful when the mock appears in test failure messages. The
michael@0 140 name is also propagated to attributes or methods of the mock:
michael@0 141
michael@0 142 .. doctest::
michael@0 143
michael@0 144 >>> mock = MagicMock(name='foo')
michael@0 145 >>> mock
michael@0 146 <MagicMock name='foo' id='...'>
michael@0 147 >>> mock.method
michael@0 148 <MagicMock name='foo.method' id='...'>
michael@0 149
michael@0 150
michael@0 151 Tracking all Calls
michael@0 152 ------------------
michael@0 153
michael@0 154 Often you want to track more than a single call to a method. The
michael@0 155 :attr:`~Mock.mock_calls` attribute records all calls
michael@0 156 to child attributes of the mock - and also to their children.
michael@0 157
michael@0 158 .. doctest::
michael@0 159
michael@0 160 >>> mock = MagicMock()
michael@0 161 >>> mock.method()
michael@0 162 <MagicMock name='mock.method()' id='...'>
michael@0 163 >>> mock.attribute.method(10, x=53)
michael@0 164 <MagicMock name='mock.attribute.method()' id='...'>
michael@0 165 >>> mock.mock_calls
michael@0 166 [call.method(), call.attribute.method(10, x=53)]
michael@0 167
michael@0 168 If you make an assertion about `mock_calls` and any unexpected methods
michael@0 169 have been called, then the assertion will fail. This is useful because as well
michael@0 170 as asserting that the calls you expected have been made, you are also checking
michael@0 171 that they were made in the right order and with no additional calls:
michael@0 172
michael@0 173 You use the :data:`call` object to construct lists for comparing with
michael@0 174 `mock_calls`:
michael@0 175
michael@0 176 .. doctest::
michael@0 177
michael@0 178 >>> expected = [call.method(), call.attribute.method(10, x=53)]
michael@0 179 >>> mock.mock_calls == expected
michael@0 180 True
michael@0 181
michael@0 182
michael@0 183 Setting Return Values and Attributes
michael@0 184 ------------------------------------
michael@0 185
michael@0 186 Setting the return values on a mock object is trivially easy:
michael@0 187
michael@0 188 .. doctest::
michael@0 189
michael@0 190 >>> mock = Mock()
michael@0 191 >>> mock.return_value = 3
michael@0 192 >>> mock()
michael@0 193 3
michael@0 194
michael@0 195 Of course you can do the same for methods on the mock:
michael@0 196
michael@0 197 .. doctest::
michael@0 198
michael@0 199 >>> mock = Mock()
michael@0 200 >>> mock.method.return_value = 3
michael@0 201 >>> mock.method()
michael@0 202 3
michael@0 203
michael@0 204 The return value can also be set in the constructor:
michael@0 205
michael@0 206 .. doctest::
michael@0 207
michael@0 208 >>> mock = Mock(return_value=3)
michael@0 209 >>> mock()
michael@0 210 3
michael@0 211
michael@0 212 If you need an attribute setting on your mock, just do it:
michael@0 213
michael@0 214 .. doctest::
michael@0 215
michael@0 216 >>> mock = Mock()
michael@0 217 >>> mock.x = 3
michael@0 218 >>> mock.x
michael@0 219 3
michael@0 220
michael@0 221 Sometimes you want to mock up a more complex situation, like for example
michael@0 222 `mock.connection.cursor().execute("SELECT 1")`. If we wanted this call to
michael@0 223 return a list, then we have to configure the result of the nested call.
michael@0 224
michael@0 225 We can use :data:`call` to construct the set of calls in a "chained call" like
michael@0 226 this for easy assertion afterwards:
michael@0 227
michael@0 228
michael@0 229 .. doctest::
michael@0 230
michael@0 231 >>> mock = Mock()
michael@0 232 >>> cursor = mock.connection.cursor.return_value
michael@0 233 >>> cursor.execute.return_value = ['foo']
michael@0 234 >>> mock.connection.cursor().execute("SELECT 1")
michael@0 235 ['foo']
michael@0 236 >>> expected = call.connection.cursor().execute("SELECT 1").call_list()
michael@0 237 >>> mock.mock_calls
michael@0 238 [call.connection.cursor(), call.connection.cursor().execute('SELECT 1')]
michael@0 239 >>> mock.mock_calls == expected
michael@0 240 True
michael@0 241
michael@0 242 It is the call to `.call_list()` that turns our call object into a list of
michael@0 243 calls representing the chained calls.
michael@0 244
michael@0 245
michael@0 246
michael@0 247 Raising exceptions with mocks
michael@0 248 -----------------------------
michael@0 249
michael@0 250 A useful attribute is :attr:`~Mock.side_effect`. If you set this to an
michael@0 251 exception class or instance then the exception will be raised when the mock
michael@0 252 is called.
michael@0 253
michael@0 254 .. doctest::
michael@0 255
michael@0 256 >>> mock = Mock(side_effect=Exception('Boom!'))
michael@0 257 >>> mock()
michael@0 258 Traceback (most recent call last):
michael@0 259 ...
michael@0 260 Exception: Boom!
michael@0 261
michael@0 262
michael@0 263 Side effect functions and iterables
michael@0 264 -----------------------------------
michael@0 265
michael@0 266 `side_effect` can also be set to a function or an iterable. The use case for
michael@0 267 `side_effect` as an iterable is where your mock is going to be called several
michael@0 268 times, and you want each call to return a different value. When you set
michael@0 269 `side_effect` to an iterable every call to the mock returns the next value
michael@0 270 from the iterable:
michael@0 271
michael@0 272 .. doctest::
michael@0 273
michael@0 274 >>> mock = MagicMock(side_effect=[4, 5, 6])
michael@0 275 >>> mock()
michael@0 276 4
michael@0 277 >>> mock()
michael@0 278 5
michael@0 279 >>> mock()
michael@0 280 6
michael@0 281
michael@0 282
michael@0 283 For more advanced use cases, like dynamically varying the return values
michael@0 284 depending on what the mock is called with, `side_effect` can be a function.
michael@0 285 The function will be called with the same arguments as the mock. Whatever the
michael@0 286 function returns is what the call returns:
michael@0 287
michael@0 288 .. doctest::
michael@0 289
michael@0 290 >>> vals = {(1, 2): 1, (2, 3): 2}
michael@0 291 >>> def side_effect(*args):
michael@0 292 ... return vals[args]
michael@0 293 ...
michael@0 294 >>> mock = MagicMock(side_effect=side_effect)
michael@0 295 >>> mock(1, 2)
michael@0 296 1
michael@0 297 >>> mock(2, 3)
michael@0 298 2
michael@0 299
michael@0 300
michael@0 301 Creating a Mock from an Existing Object
michael@0 302 ---------------------------------------
michael@0 303
michael@0 304 One problem with over use of mocking is that it couples your tests to the
michael@0 305 implementation of your mocks rather than your real code. Suppose you have a
michael@0 306 class that implements `some_method`. In a test for another class, you
michael@0 307 provide a mock of this object that *also* provides `some_method`. If later
michael@0 308 you refactor the first class, so that it no longer has `some_method` - then
michael@0 309 your tests will continue to pass even though your code is now broken!
michael@0 310
michael@0 311 `Mock` allows you to provide an object as a specification for the mock,
michael@0 312 using the `spec` keyword argument. Accessing methods / attributes on the
michael@0 313 mock that don't exist on your specification object will immediately raise an
michael@0 314 attribute error. If you change the implementation of your specification, then
michael@0 315 tests that use that class will start failing immediately without you having to
michael@0 316 instantiate the class in those tests.
michael@0 317
michael@0 318 .. doctest::
michael@0 319
michael@0 320 >>> mock = Mock(spec=SomeClass)
michael@0 321 >>> mock.old_method()
michael@0 322 Traceback (most recent call last):
michael@0 323 ...
michael@0 324 AttributeError: object has no attribute 'old_method'
michael@0 325
michael@0 326 If you want a stronger form of specification that prevents the setting
michael@0 327 of arbitrary attributes as well as the getting of them then you can use
michael@0 328 `spec_set` instead of `spec`.
michael@0 329
michael@0 330
michael@0 331
michael@0 332 Patch Decorators
michael@0 333 ================
michael@0 334
michael@0 335 .. note::
michael@0 336
michael@0 337 With `patch` it matters that you patch objects in the namespace where they
michael@0 338 are looked up. This is normally straightforward, but for a quick guide
michael@0 339 read :ref:`where to patch <where-to-patch>`.
michael@0 340
michael@0 341
michael@0 342 A common need in tests is to patch a class attribute or a module attribute,
michael@0 343 for example patching a builtin or patching a class in a module to test that it
michael@0 344 is instantiated. Modules and classes are effectively global, so patching on
michael@0 345 them has to be undone after the test or the patch will persist into other
michael@0 346 tests and cause hard to diagnose problems.
michael@0 347
michael@0 348 mock provides three convenient decorators for this: `patch`, `patch.object` and
michael@0 349 `patch.dict`. `patch` takes a single string, of the form
michael@0 350 `package.module.Class.attribute` to specify the attribute you are patching. It
michael@0 351 also optionally takes a value that you want the attribute (or class or
michael@0 352 whatever) to be replaced with. 'patch.object' takes an object and the name of
michael@0 353 the attribute you would like patched, plus optionally the value to patch it
michael@0 354 with.
michael@0 355
michael@0 356 `patch.object`:
michael@0 357
michael@0 358 .. doctest::
michael@0 359
michael@0 360 >>> original = SomeClass.attribute
michael@0 361 >>> @patch.object(SomeClass, 'attribute', sentinel.attribute)
michael@0 362 ... def test():
michael@0 363 ... assert SomeClass.attribute == sentinel.attribute
michael@0 364 ...
michael@0 365 >>> test()
michael@0 366 >>> assert SomeClass.attribute == original
michael@0 367
michael@0 368 >>> @patch('package.module.attribute', sentinel.attribute)
michael@0 369 ... def test():
michael@0 370 ... from package.module import attribute
michael@0 371 ... assert attribute is sentinel.attribute
michael@0 372 ...
michael@0 373 >>> test()
michael@0 374
michael@0 375 If you are patching a module (including `__builtin__`) then use `patch`
michael@0 376 instead of `patch.object`:
michael@0 377
michael@0 378 .. doctest::
michael@0 379
michael@0 380 >>> mock = MagicMock(return_value = sentinel.file_handle)
michael@0 381 >>> with patch('__builtin__.open', mock):
michael@0 382 ... handle = open('filename', 'r')
michael@0 383 ...
michael@0 384 >>> mock.assert_called_with('filename', 'r')
michael@0 385 >>> assert handle == sentinel.file_handle, "incorrect file handle returned"
michael@0 386
michael@0 387 The module name can be 'dotted', in the form `package.module` if needed:
michael@0 388
michael@0 389 .. doctest::
michael@0 390
michael@0 391 >>> @patch('package.module.ClassName.attribute', sentinel.attribute)
michael@0 392 ... def test():
michael@0 393 ... from package.module import ClassName
michael@0 394 ... assert ClassName.attribute == sentinel.attribute
michael@0 395 ...
michael@0 396 >>> test()
michael@0 397
michael@0 398 A nice pattern is to actually decorate test methods themselves:
michael@0 399
michael@0 400 .. doctest::
michael@0 401
michael@0 402 >>> class MyTest(unittest2.TestCase):
michael@0 403 ... @patch.object(SomeClass, 'attribute', sentinel.attribute)
michael@0 404 ... def test_something(self):
michael@0 405 ... self.assertEqual(SomeClass.attribute, sentinel.attribute)
michael@0 406 ...
michael@0 407 >>> original = SomeClass.attribute
michael@0 408 >>> MyTest('test_something').test_something()
michael@0 409 >>> assert SomeClass.attribute == original
michael@0 410
michael@0 411 If you want to patch with a Mock, you can use `patch` with only one argument
michael@0 412 (or `patch.object` with two arguments). The mock will be created for you and
michael@0 413 passed into the test function / method:
michael@0 414
michael@0 415 .. doctest::
michael@0 416
michael@0 417 >>> class MyTest(unittest2.TestCase):
michael@0 418 ... @patch.object(SomeClass, 'static_method')
michael@0 419 ... def test_something(self, mock_method):
michael@0 420 ... SomeClass.static_method()
michael@0 421 ... mock_method.assert_called_with()
michael@0 422 ...
michael@0 423 >>> MyTest('test_something').test_something()
michael@0 424
michael@0 425 You can stack up multiple patch decorators using this pattern:
michael@0 426
michael@0 427 .. doctest::
michael@0 428
michael@0 429 >>> class MyTest(unittest2.TestCase):
michael@0 430 ... @patch('package.module.ClassName1')
michael@0 431 ... @patch('package.module.ClassName2')
michael@0 432 ... def test_something(self, MockClass2, MockClass1):
michael@0 433 ... self.assertTrue(package.module.ClassName1 is MockClass1)
michael@0 434 ... self.assertTrue(package.module.ClassName2 is MockClass2)
michael@0 435 ...
michael@0 436 >>> MyTest('test_something').test_something()
michael@0 437
michael@0 438 When you nest patch decorators the mocks are passed in to the decorated
michael@0 439 function in the same order they applied (the normal *python* order that
michael@0 440 decorators are applied). This means from the bottom up, so in the example
michael@0 441 above the mock for `test_module.ClassName2` is passed in first.
michael@0 442
michael@0 443 There is also :func:`patch.dict` for setting values in a dictionary just
michael@0 444 during a scope and restoring the dictionary to its original state when the test
michael@0 445 ends:
michael@0 446
michael@0 447 .. doctest::
michael@0 448
michael@0 449 >>> foo = {'key': 'value'}
michael@0 450 >>> original = foo.copy()
michael@0 451 >>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):
michael@0 452 ... assert foo == {'newkey': 'newvalue'}
michael@0 453 ...
michael@0 454 >>> assert foo == original
michael@0 455
michael@0 456 `patch`, `patch.object` and `patch.dict` can all be used as context managers.
michael@0 457
michael@0 458 Where you use `patch` to create a mock for you, you can get a reference to the
michael@0 459 mock using the "as" form of the with statement:
michael@0 460
michael@0 461 .. doctest::
michael@0 462
michael@0 463 >>> class ProductionClass(object):
michael@0 464 ... def method(self):
michael@0 465 ... pass
michael@0 466 ...
michael@0 467 >>> with patch.object(ProductionClass, 'method') as mock_method:
michael@0 468 ... mock_method.return_value = None
michael@0 469 ... real = ProductionClass()
michael@0 470 ... real.method(1, 2, 3)
michael@0 471 ...
michael@0 472 >>> mock_method.assert_called_with(1, 2, 3)
michael@0 473
michael@0 474
michael@0 475 As an alternative `patch`, `patch.object` and `patch.dict` can be used as
michael@0 476 class decorators. When used in this way it is the same as applying the
michael@0 477 decorator indvidually to every method whose name starts with "test".
michael@0 478
michael@0 479 For some more advanced examples, see the :ref:`further-examples` page.

mercurial