From 72dccab15f4230bf6d0bdf4cc47f08c3577a2c8b Mon Sep 17 00:00:00 2001 From: Marco Buttu Date: Sun, 26 Mar 2017 10:04:37 +0200 Subject: [PATCH 1/4] bpo-27200: fix unittest.mock doctests. --- Doc/conf.py | 32 +++++++ Doc/includes/__init__.py | 0 Doc/includes/unittest_mock/__init__.py | 0 Doc/includes/unittest_mock/mymodule.py | 9 ++ .../unittest_mock/package/__init__.py | 0 Doc/includes/unittest_mock/package/module.py | 11 +++ Doc/library/unittest.mock-examples.rst | 75 ++++++++++++++-- Doc/library/unittest.mock.rst | 87 +++++++++++++++++-- 8 files changed, 199 insertions(+), 15 deletions(-) create mode 100644 Doc/includes/__init__.py create mode 100644 Doc/includes/unittest_mock/__init__.py create mode 100644 Doc/includes/unittest_mock/mymodule.py create mode 100644 Doc/includes/unittest_mock/package/__init__.py create mode 100644 Doc/includes/unittest_mock/package/module.py diff --git a/Doc/conf.py b/Doc/conf.py index c1c2472a19630a0..d38e49c76d3a24d 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -199,3 +199,35 @@ # Relative filename of the reference count data file. refcount_file = 'data/refcounts.dat' + + +# Global setup +# ------------ + +# When we execute the doctests under Sphinx, the __main__ module is +# the sphinx-build script, that is why we can not use the __main__ +# module as we do in the REPL. For instance, this example does not work: +# +# >>> b = 33 +# >>> import __main__ +# >>> __main__.b +# 33 +# +# To solve the problem, we can set `doctest_global_setup` in the following way. +doctest_global_setup = """ +import sys +import __main__ + +# keep a reference to __main__ +__main = __main__ + +class ProxyModule(object): + def __init__(self): + self.__dict__ = globals() + +sys.modules['__main__'] = ProxyModule() +""" + +doctest_global_cleanup = """ +sys.modules['__main__'] = __main +""" diff --git a/Doc/includes/__init__.py b/Doc/includes/__init__.py new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/Doc/includes/unittest_mock/__init__.py b/Doc/includes/unittest_mock/__init__.py new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/Doc/includes/unittest_mock/mymodule.py b/Doc/includes/unittest_mock/mymodule.py new file mode 100644 index 000000000000000..a6c819267cf69a2 --- /dev/null +++ b/Doc/includes/unittest_mock/mymodule.py @@ -0,0 +1,9 @@ +def frob(val): + pass + +def grob(val): + "First frob and then clear val" + frob(val) + val.clear() + +Class1 = Class2 = Foo = Bar = Spam = SomeClass = date = None diff --git a/Doc/includes/unittest_mock/package/__init__.py b/Doc/includes/unittest_mock/package/__init__.py new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/Doc/includes/unittest_mock/package/module.py b/Doc/includes/unittest_mock/package/module.py new file mode 100644 index 000000000000000..3fe18f3e4de803d --- /dev/null +++ b/Doc/includes/unittest_mock/package/module.py @@ -0,0 +1,11 @@ +attribute = 'attr' + +class ClassName: + attribute = None + + +class ClassName1: + pass + +class ClassName2: + pass diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst index 05f33740d7527a9..dd544d21f545b03 100644 --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -6,6 +6,34 @@ .. versionadded:: 3.3 +.. testsetup:: + + import unittest + import unittest_mock.mymodule as mymodule + import unittest_mock.package as package + + # The examples require mymodule to have the following attributes + for attr in ['Class1', 'Class2', 'Foo', 'Bar', 'Spam', 'SomeClass', 'date']: + setattr(mymodule, attr, None) + + # This allows us to import unittest_mock.mymodule as + # ``import module`` and unittest_mock.package as ``import package`` + import sys + sys.modules['mymodule'] = mymodule + sys.modules['package'] = package + + class SomeClass: + attribute = None + +.. testcleanup:: + + for module in [ + 'unittest_mock', + 'unittest_mock.package', + 'unittest_mock.mymodule', + 'package', + 'mymodule']: + del sys.modules[module] .. _getting-started: @@ -23,6 +51,7 @@ Common uses for :class:`Mock` objects include: You might want to replace a method on an object to check that it is called with the correct arguments by another part of the system: + >>> from unittest.mock import MagicMock >>> real = SomeClass() >>> real.method = MagicMock(name='method') >>> real.method(3, 4, 5, key='value') @@ -77,6 +106,7 @@ an object then it calls ``close`` on it. So to test it we need to pass in an object with a ``close`` method and check that it was called correctly. + >>> from unittest.mock import Mock >>> real = ProductionClass() >>> mock = Mock() >>> real.closer(mock) @@ -102,10 +132,11 @@ mock. The ``Foo`` instance is the result of calling the mock, so it is configure by modifying the mock :attr:`~Mock.return_value`. >>> def some_function(): - ... instance = module.Foo() + ... instance = mymodule.Foo() ... return instance.method() ... - >>> with patch('module.Foo') as mock: + >>> from unittest.mock import patch + >>> with patch('mymodule.Foo') as mock: ... instance = mock.return_value ... instance.method.return_value = 'the result' ... result = some_function() @@ -149,6 +180,7 @@ that they were made in the right order and with no additional calls: You use the :data:`call` object to construct lists for comparing with ``mock_calls``: + >>> from unittest.mock import call >>> expected = [call.method(), call.attribute.method(10, x=53)] >>> mock.mock_calls == expected True @@ -323,6 +355,7 @@ with. ``patch.object``: + >>> from unittest.mock import sentinel >>> original = SomeClass.attribute >>> @patch.object(SomeClass, 'attribute', sentinel.attribute) ... def test(): @@ -372,6 +405,10 @@ If you want to patch with a Mock, you can use :func:`patch` with only one argume (or :func:`patch.object` with two arguments). The mock will be created for you and passed into the test function / method: + >>> class SomeClass: + ... def static_method(): + ... pass + ... >>> class MyTest(unittest.TestCase): ... @patch.object(SomeClass, 'static_method') ... def test_something(self, mock_method): @@ -460,6 +497,19 @@ testable way in the first place... So, suppose we have some code that looks a little bit like this: +.. testsetup:: backend_provider + + from unittest.mock import Mock, call + class BackendProvider: + def get_endpoint(self, par): + class Endpoint: + def create_call(self, par1, par2): + class Call: + def start_call(self): + ... + +.. doctest:: backend_provider + >>> class Something: ... def __init__(self): ... self.backend = BackendProvider() @@ -487,6 +537,8 @@ response object for it. To set the response as the return value for that final We can do that in a slightly nicer way using the :meth:`~Mock.configure_mock` method to directly set the return value for us: +.. doctest:: backend_provider + >>> something = Something() >>> mock_response = Mock(spec=open) >>> mock_backend = Mock() @@ -496,6 +548,8 @@ method to directly set the return value for us: With these we monkey patch the "mock backend" in place and can make the real call: +.. doctest:: backend_provider + >>> something.backend = mock_backend >>> something.method() @@ -504,6 +558,8 @@ assert. A chained call is several calls in one line of code, so there will be several entries in ``mock_calls``. We can use :meth:`call.call_list` to create this list of calls for us: +.. doctest:: backend_provider + >>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call() >>> call_list = chained.call_list() >>> assert mock_backend.mock_calls == call_list @@ -603,7 +659,7 @@ methods on the class. A test method is identified by methods whose names start with ``test``: >>> @patch('mymodule.SomeClass') - ... class MyTest(TestCase): + ... class MyTest(unittest.TestCase): ... ... def test_one(self, MockSomeClass): ... self.assertIs(mymodule.SomeClass, MockSomeClass) @@ -622,7 +678,7 @@ with ``test``: An alternative way of managing patches is to use the :ref:`start-and-stop`. These allow you to move the patching into your ``setUp`` and ``tearDown`` methods. - >>> class MyTest(TestCase): + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... self.patcher = patch('mymodule.foo') ... self.mock_foo = self.patcher.start() @@ -634,13 +690,14 @@ These allow you to move the patching into your ``setUp`` and ``tearDown`` method ... self.patcher.stop() ... >>> MyTest('test_foo').run() + If you use this technique you must ensure that the patching is "undone" by calling ``stop``. This can be fiddlier than you might think, because if an exception is raised in the setUp then tearDown is not called. :meth:`unittest.TestCase.addCleanup` makes this easier: - >>> class MyTest(TestCase): + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... patcher = patch('mymodule.foo') ... self.addCleanup(patcher.stop) @@ -650,6 +707,7 @@ exception is raised in the setUp then tearDown is not called. ... self.assertIs(mymodule.foo, self.mock_foo) ... >>> MyTest('test_foo').run() + Mocking Unbound Methods @@ -856,7 +914,7 @@ Using patch as a context manager is nice, but if you do multiple patches you can end up with nested with statements indenting further and further to the right: - >>> class MyTest(TestCase): + >>> class MyTest(unittest.TestCase): ... ... def test_foo(self): ... with patch('mymodule.Foo') as mock_foo: @@ -875,7 +933,7 @@ achieve the same effect without the nested indentation. A simple helper method, ``create_patch``, puts the patch in place and returns the created mock for us: - >>> class MyTest(TestCase): + >>> class MyTest(unittest.TestCase): ... ... def create_patch(self, name): ... patcher = patch(name) @@ -894,6 +952,7 @@ for us: ... >>> original = mymodule.Foo >>> MyTest('test_foo').run() + >>> assert mymodule.Foo is original @@ -968,7 +1027,7 @@ mock methods and attributes: [call('a'), call('c'), call('d'), call('b'), call('d')] >>> mock.__setitem__.call_args_list [call('b', 'fish'), call('d', 'eggs')] - >>> my_dict + >>> my_dict # doctest: +SKIP {'a': 1, 'c': 3, 'b': 'fish', 'd': 'eggs'} diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index cbe0c9adb8a37bf..cf8137d46e78ff8 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -10,6 +10,29 @@ .. versionadded:: 3.3 +.. testsetup:: + + import unittest + import unittest_mock.package.module as module + import unittest_mock.package as package + + # This allows us to import unittest_mock.package.module as + # ``import module`` and unittest_mock.package as ``import package`` + import sys + sys.modules['module'] = module + sys.modules['package'] = package + +.. testcleanup:: + + for module in [ + 'unittest_mock', + 'unittest_mock.package', + 'unittest_mock.package.module', + 'package', + 'module']: + del sys.modules[module] + + **Source code:** :source:`Lib/unittest/mock.py` -------------- @@ -47,6 +70,10 @@ can configure them, to specify return values or limit what attributes are available, and then make assertions about how they have been used: >>> from unittest.mock import MagicMock + >>> class ProductionClass: + ... def method(self): + ... pass + ... >>> thing = ProductionClass() >>> thing.method = MagicMock(return_value=3) >>> thing.method(3, 4, 5, key='value') @@ -56,6 +83,7 @@ available, and then make assertions about how they have been used: :attr:`side_effect` allows you to perform side effects, including raising an exception when a mock is called: + >>> from unittest.mock import Mock >>> mock = Mock(side_effect=KeyError('foo')) >>> mock() Traceback (most recent call last): @@ -348,6 +376,7 @@ the *new_callable* argument to :func:`patch`. >>> mock(2) >>> mock(3) >>> mock(4) + >>> from unittest.mock import call >>> calls = [call(2), call(3)] >>> mock.assert_has_calls(calls) >>> calls = [call(4), call(2), call(3)] @@ -504,6 +533,7 @@ the *new_callable* argument to :func:`patch`. the normal way: >>> mock = Mock() + >>> from unittest.mock import sentinel >>> mock.return_value.attribute = sentinel.Attribute >>> mock.return_value() @@ -553,6 +583,7 @@ the *new_callable* argument to :func:`patch`. Using a callable: + >>> from unittest.mock import DEFAULT >>> mock = Mock(return_value=3) >>> def side_effect(*args, **kwargs): ... return DEFAULT @@ -709,6 +740,13 @@ the *new_callable* argument to :func:`patch`. Mock objects that use a class or an instance as a :attr:`spec` or :attr:`spec_set` are able to pass :func:`isinstance` tests: + >>> class SomeClass: + ... def static_method(par): + ... pass + ... @classmethod + ... def class_method(cls, par): + ... pass + ... >>> mock = Mock(spec=SomeClass) >>> isinstance(mock, SomeClass) True @@ -776,6 +814,7 @@ apply to method calls on the mock object. Fetching a :class:`PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. + >>> from unittest.mock import PropertyMock >>> class Foo: ... @property ... def foo(self): @@ -1162,6 +1201,7 @@ The *new_callable* argument is useful where you want to use an alternative class to the default :class:`MagicMock` for the created mock. For example, if you wanted a :class:`NonCallableMock` to be used: + >>> from unittest.mock import NonCallableMock >>> thing = object() >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing: ... assert thing is mock_thing @@ -1424,7 +1464,7 @@ the call to ``patcher.start``. A typical use case for this might be for doing multiple patches in the ``setUp`` method of a :class:`TestCase`: - >>> class MyTest(TestCase): + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... self.patcher1 = patch('package.module.Class1') ... self.patcher2 = patch('package.module.Class2') @@ -1440,6 +1480,7 @@ method of a :class:`TestCase`: ... assert package.module.Class2 is self.MockClass2 ... >>> MyTest('test_something').run() + .. caution:: @@ -1448,7 +1489,7 @@ method of a :class:`TestCase`: exception is raised in the ``setUp`` then ``tearDown`` is not called. :meth:`unittest.TestCase.addCleanup` makes this easier: - >>> class MyTest(TestCase): + >>> class MyTest(unittest.TestCase): ... def setUp(self): ... patcher = patch('package.module.Class') ... self.MockClass = patcher.start() @@ -1476,6 +1517,13 @@ patch builtins You can patch any builtins within a module. The following example patches builtin :func:`ord`: +.. testsetup:: ord + + from builtins import ord + from unittest.mock import patch + +.. doctest:: ord + >>> @patch('__main__.ord') ... def test(mock_ord): ... mock_ord.return_value = 101 @@ -1496,6 +1544,17 @@ start with ``'test'`` as being test methods. This is the same way that the It is possible that you want to use a different prefix for your tests. You can inform the patchers of the different prefix by setting ``patch.TEST_PREFIX``: +.. testsetup:: test-prefix + + from unittest.mock import patch + TEST_PREFIX = patch.TEST_PREFIX + +.. testcleanup:: test-prefix + + patch.TEST_PREFIX = TEST_PREFIX + +.. doctest:: test-prefix + >>> patch.TEST_PREFIX = 'foo' >>> value = 3 >>> @@ -1930,7 +1989,7 @@ arguments are a dictionary: >>> args, kwargs = kall >>> args (1, 2, 3) - >>> kwargs + >>> kwargs # doctest: +SKIP {'arg2': 'two', 'arg': 'one'} >>> args is kall[0] True @@ -1946,7 +2005,7 @@ arguments are a dictionary: 'foo' >>> args (4, 5, 6) - >>> kwargs + >>> kwargs # doctest: +SKIP {'arg2': 'three', 'arg': 'two'} >>> name is m.mock_calls[0][0] True @@ -1994,6 +2053,7 @@ To ignore certain arguments you can pass in objects that compare equal to :meth:`~Mock.assert_called_once_with` will then succeed no matter what was passed in. + >>> from unittest.mock import ANY >>> mock = Mock(return_value=None) >>> mock('foo', bar=object()) >>> mock.assert_called_once_with('foo', bar=ANY) @@ -2027,12 +2087,15 @@ If the mock was created with a *spec* (or *autospec* of course) then all the attributes from the original are shown, even if they haven't been accessed yet: +.. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> dir(Mock()) ['assert_any_call', + 'assert_called', + 'assert_called_once', 'assert_called_once_with', 'assert_called_with', - 'assert_has_calls', - 'attach_mock', ... >>> from urllib import request >>> dir(Mock(spec=request)) @@ -2046,7 +2109,7 @@ Many of the not-very-useful (private to :class:`Mock` rather than the thing bein mocked) underscore and double underscore prefixed attributes have been filtered from the result of calling :func:`dir` on a :class:`Mock`. If you dislike this behaviour you can switch it off by setting the module level switch -:data:`FILTER_DIR`: +:data:`FILTER_DIR`:: >>> from unittest import mock >>> mock.FILTER_DIR = False @@ -2108,6 +2171,14 @@ The issue is that even if you mock out the call to :func:`open` it is the Mocking context managers with a :class:`MagicMock` is common enough and fiddly enough that a helper function is useful. +.. testsetup:: open + + from builtins import open + from unittest.mock import patch + +.. doctest:: open + + >>> from unittest.mock import mock_open >>> m = mock_open() >>> with patch('__main__.open', m): ... with open('foo', 'w') as h: @@ -2124,6 +2195,8 @@ enough that a helper function is useful. And for reading files: +.. doctest:: open + >>> with patch('__main__.open', mock_open(read_data='bibble')) as m: ... with open('foo') as h: ... result = h.read() From 232cc7d054093bca069029f9b10590032981b4a2 Mon Sep 17 00:00:00 2001 From: Marco Buttu Date: Thu, 27 Apr 2017 11:50:22 +0200 Subject: [PATCH 2/4] bpo-27200: skip the test in the same way of PR-604 --- Doc/includes/unittest_mock/package/module.py | 1 + Doc/library/unittest.mock.rst | 29 +++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Doc/includes/unittest_mock/package/module.py b/Doc/includes/unittest_mock/package/module.py index 3fe18f3e4de803d..6fe1f5d07a0bba1 100644 --- a/Doc/includes/unittest_mock/package/module.py +++ b/Doc/includes/unittest_mock/package/module.py @@ -7,5 +7,6 @@ class ClassName: class ClassName1: pass + class ClassName2: pass diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index cf8137d46e78ff8..f0e5f1a125bf0e2 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -2109,19 +2109,22 @@ Many of the not-very-useful (private to :class:`Mock` rather than the thing bein mocked) underscore and double underscore prefixed attributes have been filtered from the result of calling :func:`dir` on a :class:`Mock`. If you dislike this behaviour you can switch it off by setting the module level switch -:data:`FILTER_DIR`:: - - >>> from unittest import mock - >>> mock.FILTER_DIR = False - >>> dir(mock.Mock()) - ['_NonCallableMock__get_return_value', - '_NonCallableMock__get_side_effect', - '_NonCallableMock__return_value_doc', - '_NonCallableMock__set_return_value', - '_NonCallableMock__set_side_effect', - '__call__', - '__class__', - ... +:data:`FILTER_DIR`: + +.. doctest:: + :options: +SKIP + + >>> from unittest import mock + >>> mock.FILTER_DIR = False + >>> dir(mock.Mock()) + ['_NonCallableMock__get_return_value', + '_NonCallableMock__get_side_effect', + '_NonCallableMock__return_value_doc', + '_NonCallableMock__set_return_value', + '_NonCallableMock__set_side_effect', + '__call__', + '__class__', + ... Alternatively you can just use ``vars(my_mock)`` (instance members) and ``dir(type(my_mock))`` (type members) to bypass the filtering irrespective of From b38c57d5277b779d9708c71cdbcf79c312eb937b Mon Sep 17 00:00:00 2001 From: Marco Buttu Date: Thu, 27 Apr 2017 16:12:36 +0200 Subject: [PATCH 3/4] bpo-27200: skip all tests that do not pass --- Doc/conf.py | 32 - Doc/includes/__init__.py | 0 Doc/includes/unittest_mock/__init__.py | 0 Doc/includes/unittest_mock/mymodule.py | 9 - .../unittest_mock/package/__init__.py | 0 Doc/includes/unittest_mock/package/module.py | 12 - Doc/library/unittest.mock-examples.rst | 467 ++++++------ Doc/library/unittest.mock.rst | 678 +++++++++--------- 8 files changed, 594 insertions(+), 604 deletions(-) delete mode 100644 Doc/includes/__init__.py delete mode 100644 Doc/includes/unittest_mock/__init__.py delete mode 100644 Doc/includes/unittest_mock/mymodule.py delete mode 100644 Doc/includes/unittest_mock/package/__init__.py delete mode 100644 Doc/includes/unittest_mock/package/module.py diff --git a/Doc/conf.py b/Doc/conf.py index d38e49c76d3a24d..c1c2472a19630a0 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -199,35 +199,3 @@ # Relative filename of the reference count data file. refcount_file = 'data/refcounts.dat' - - -# Global setup -# ------------ - -# When we execute the doctests under Sphinx, the __main__ module is -# the sphinx-build script, that is why we can not use the __main__ -# module as we do in the REPL. For instance, this example does not work: -# -# >>> b = 33 -# >>> import __main__ -# >>> __main__.b -# 33 -# -# To solve the problem, we can set `doctest_global_setup` in the following way. -doctest_global_setup = """ -import sys -import __main__ - -# keep a reference to __main__ -__main = __main__ - -class ProxyModule(object): - def __init__(self): - self.__dict__ = globals() - -sys.modules['__main__'] = ProxyModule() -""" - -doctest_global_cleanup = """ -sys.modules['__main__'] = __main -""" diff --git a/Doc/includes/__init__.py b/Doc/includes/__init__.py deleted file mode 100644 index e69de29bb2d1d64..000000000000000 diff --git a/Doc/includes/unittest_mock/__init__.py b/Doc/includes/unittest_mock/__init__.py deleted file mode 100644 index e69de29bb2d1d64..000000000000000 diff --git a/Doc/includes/unittest_mock/mymodule.py b/Doc/includes/unittest_mock/mymodule.py deleted file mode 100644 index a6c819267cf69a2..000000000000000 --- a/Doc/includes/unittest_mock/mymodule.py +++ /dev/null @@ -1,9 +0,0 @@ -def frob(val): - pass - -def grob(val): - "First frob and then clear val" - frob(val) - val.clear() - -Class1 = Class2 = Foo = Bar = Spam = SomeClass = date = None diff --git a/Doc/includes/unittest_mock/package/__init__.py b/Doc/includes/unittest_mock/package/__init__.py deleted file mode 100644 index e69de29bb2d1d64..000000000000000 diff --git a/Doc/includes/unittest_mock/package/module.py b/Doc/includes/unittest_mock/package/module.py deleted file mode 100644 index 6fe1f5d07a0bba1..000000000000000 --- a/Doc/includes/unittest_mock/package/module.py +++ /dev/null @@ -1,12 +0,0 @@ -attribute = 'attr' - -class ClassName: - attribute = None - - -class ClassName1: - pass - - -class ClassName2: - pass diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst index dd544d21f545b03..138ddba403ec434 100644 --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -9,31 +9,8 @@ .. testsetup:: import unittest - import unittest_mock.mymodule as mymodule - import unittest_mock.package as package + from unittest.mock import MagicMock, sentinel, patch - # The examples require mymodule to have the following attributes - for attr in ['Class1', 'Class2', 'Foo', 'Bar', 'Spam', 'SomeClass', 'date']: - setattr(mymodule, attr, None) - - # This allows us to import unittest_mock.mymodule as - # ``import module`` and unittest_mock.package as ``import package`` - import sys - sys.modules['mymodule'] = mymodule - sys.modules['package'] = package - - class SomeClass: - attribute = None - -.. testcleanup:: - - for module in [ - 'unittest_mock', - 'unittest_mock.package', - 'unittest_mock.mymodule', - 'package', - 'mymodule']: - del sys.modules[module] .. _getting-started: @@ -51,11 +28,14 @@ Common uses for :class:`Mock` objects include: You might want to replace a method on an object to check that it is called with the correct arguments by another part of the system: - >>> from unittest.mock import MagicMock - >>> real = SomeClass() - >>> real.method = MagicMock(name='method') - >>> real.method(3, 4, 5, key='value') - +.. doctest:: + :options: +SKIP + + >>> from unittest.mock import MagicMock + >>> real = SomeClass() + >>> real.method = MagicMock(name='method') + >>> real.method(3, 4, 5, key='value') + Once our mock has been used (``real.method`` in this example) it has methods and attributes that allow you to make assertions about how it has been used. @@ -131,16 +111,19 @@ and calls a method on it. The call to :func:`patch` replaces the class ``Foo`` w mock. The ``Foo`` instance is the result of calling the mock, so it is configured by modifying the mock :attr:`~Mock.return_value`. - >>> def some_function(): - ... instance = mymodule.Foo() - ... return instance.method() - ... - >>> from unittest.mock import patch - >>> with patch('mymodule.Foo') as mock: - ... instance = mock.return_value - ... instance.method.return_value = 'the result' - ... result = some_function() - ... assert result == 'the result' +.. doctest:: + :options: +SKIP + + >>> def some_function(): + ... instance = mymodule.Foo() + ... return instance.method() + ... + >>> from unittest.mock import patch + >>> with patch('mymodule.Foo') as mock: + ... instance = mock.return_value + ... instance.method.return_value = 'the result' + ... result = some_function() + ... assert result == 'the result' Naming your mocks @@ -303,11 +286,14 @@ attribute error. If you change the implementation of your specification, then tests that use that class will start failing immediately without you having to instantiate the class in those tests. - >>> mock = Mock(spec=SomeClass) - >>> mock.old_method() - Traceback (most recent call last): - ... - AttributeError: object has no attribute 'old_method' +.. doctest:: + :options: +SKIP + + >>> mock = Mock(spec=SomeClass) + >>> mock.old_method() + Traceback (most recent call last): + ... + AttributeError: object has no attribute 'old_method' Using a specification also enables a smarter matching of calls made to the mock, regardless of whether some parameters were passed as positional or @@ -355,67 +341,78 @@ with. ``patch.object``: - >>> from unittest.mock import sentinel - >>> original = SomeClass.attribute - >>> @patch.object(SomeClass, 'attribute', sentinel.attribute) - ... def test(): - ... assert SomeClass.attribute == sentinel.attribute - ... - >>> test() - >>> assert SomeClass.attribute == original +.. doctest:: + :options: +SKIP - >>> @patch('package.module.attribute', sentinel.attribute) - ... def test(): - ... from package.module import attribute - ... assert attribute is sentinel.attribute - ... - >>> test() + >>> from unittest.mock import sentinel + >>> original = SomeClass.attribute + >>> @patch.object(SomeClass, 'attribute', sentinel.attribute) + ... def test(): + ... assert SomeClass.attribute == sentinel.attribute + ... + >>> test() + >>> assert SomeClass.attribute == original + + >>> @patch('package.module.attribute', sentinel.attribute) + ... def test(): + ... from package.module import attribute + ... assert attribute is sentinel.attribute + ... + >>> test() If you are patching a module (including :mod:`builtins`) then use :func:`patch` instead of :func:`patch.object`: - >>> mock = MagicMock(return_value=sentinel.file_handle) - >>> with patch('builtins.open', mock): - ... handle = open('filename', 'r') - ... - >>> mock.assert_called_with('filename', 'r') - >>> assert handle == sentinel.file_handle, "incorrect file handle returned" +.. doctest:: + :options: +SKIP + + >>> mock = MagicMock(return_value=sentinel.file_handle) + >>> with patch('builtins.open', mock): + ... handle = open('filename', 'r') + ... + >>> mock.assert_called_with('filename', 'r') + >>> assert handle == sentinel.file_handle, "incorrect file handle returned" The module name can be 'dotted', in the form ``package.module`` if needed: - >>> @patch('package.module.ClassName.attribute', sentinel.attribute) - ... def test(): - ... from package.module import ClassName - ... assert ClassName.attribute == sentinel.attribute - ... - >>> test() +.. doctest:: + :options: +SKIP + + >>> @patch('package.module.ClassName.attribute', sentinel.attribute) + ... def test(): + ... from package.module import ClassName + ... assert ClassName.attribute == sentinel.attribute + ... + >>> test() A nice pattern is to actually decorate test methods themselves: - >>> class MyTest(unittest.TestCase): - ... @patch.object(SomeClass, 'attribute', sentinel.attribute) - ... def test_something(self): - ... self.assertEqual(SomeClass.attribute, sentinel.attribute) - ... - >>> original = SomeClass.attribute - >>> MyTest('test_something').test_something() - >>> assert SomeClass.attribute == original +.. doctest:: + :options: +SKIP + + >>> class MyTest(unittest.TestCase): + ... @patch.object(SomeClass, 'attribute', sentinel.attribute) + ... def test_something(self): + ... self.assertEqual(SomeClass.attribute, sentinel.attribute) + ... + >>> original = SomeClass.attribute + >>> MyTest('test_something').test_something() + >>> assert SomeClass.attribute == original If you want to patch with a Mock, you can use :func:`patch` with only one argument (or :func:`patch.object` with two arguments). The mock will be created for you and passed into the test function / method: - >>> class SomeClass: - ... def static_method(): - ... pass - ... - >>> class MyTest(unittest.TestCase): - ... @patch.object(SomeClass, 'static_method') - ... def test_something(self, mock_method): - ... SomeClass.static_method() - ... mock_method.assert_called_with() - ... - >>> MyTest('test_something').test_something() +.. doctest:: + :options: +SKIP + + >>> class MyTest(unittest.TestCase): + ... @patch.object(SomeClass, 'static_method') + ... def test_something(self, mock_method): + ... SomeClass.static_method() + ... mock_method.assert_called_with() + ... + >>> MyTest('test_something').test_something() You can stack up multiple patch decorators using this pattern: @@ -426,7 +423,7 @@ You can stack up multiple patch decorators using this pattern: ... self.assertIs(package.module.ClassName1, MockClass1) ... self.assertIs(package.module.ClassName2, MockClass2) ... - >>> MyTest('test_something').test_something() + >>> MyTest('test_something').test_something() # doctest: +SKIP When you nest patch decorators the mocks are passed in to the decorated function in the same order they applied (the normal *python* order that @@ -497,25 +494,15 @@ testable way in the first place... So, suppose we have some code that looks a little bit like this: -.. testsetup:: backend_provider - - from unittest.mock import Mock, call - class BackendProvider: - def get_endpoint(self, par): - class Endpoint: - def create_call(self, par1, par2): - class Call: - def start_call(self): - ... +.. doctest:: + :options: +SKIP -.. doctest:: backend_provider - - >>> class Something: - ... def __init__(self): - ... self.backend = BackendProvider() - ... def method(self): - ... response = self.backend.get_endpoint('foobar').create_call('spam', 'eggs').start_call() - ... # more code + >>> class Something: + ... def __init__(self): + ... self.backend = BackendProvider() + ... def method(self): + ... response = self.backend.get_endpoint('foobar').create_call('spam', 'eggs').start_call() + ... # more code Assuming that ``BackendProvider`` is already well tested, how do we test ``method()``? Specifically, we want to test that the code section ``# more @@ -537,32 +524,35 @@ response object for it. To set the response as the return value for that final We can do that in a slightly nicer way using the :meth:`~Mock.configure_mock` method to directly set the return value for us: -.. doctest:: backend_provider +.. doctest:: + :options: +SKIP - >>> something = Something() - >>> mock_response = Mock(spec=open) - >>> mock_backend = Mock() - >>> config = {'get_endpoint.return_value.create_call.return_value.start_call.return_value': mock_response} - >>> mock_backend.configure_mock(**config) + >>> something = Something() + >>> mock_response = Mock(spec=open) + >>> mock_backend = Mock() + >>> config = {'get_endpoint.return_value.create_call.return_value.start_call.return_value': mock_response} + >>> mock_backend.configure_mock(**config) With these we monkey patch the "mock backend" in place and can make the real call: -.. doctest:: backend_provider +.. doctest:: + :options: +SKIP - >>> something.backend = mock_backend - >>> something.method() + >>> something.backend = mock_backend + >>> something.method() Using :attr:`~Mock.mock_calls` we can check the chained call with a single assert. A chained call is several calls in one line of code, so there will be several entries in ``mock_calls``. We can use :meth:`call.call_list` to create this list of calls for us: -.. doctest:: backend_provider +.. doctest:: + :options: +SKIP - >>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call() - >>> call_list = chained.call_list() - >>> assert mock_backend.mock_calls == call_list + >>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call() + >>> call_list = chained.call_list() + >>> assert mock_backend.mock_calls == call_list Partial mocking @@ -583,14 +573,17 @@ attribute on the mock date class is then set to a lambda function that returns a real date. When the mock date class is called a real date will be constructed and returned by ``side_effect``. - >>> from datetime import date - >>> with patch('mymodule.date') as mock_date: - ... mock_date.today.return_value = date(2010, 10, 8) - ... mock_date.side_effect = lambda *args, **kw: date(*args, **kw) - ... - ... assert mymodule.date.today() == date(2010, 10, 8) - ... assert mymodule.date(2009, 6, 8) == date(2009, 6, 8) - ... +.. doctest:: + :options: +SKIP + + >>> from datetime import date + >>> with patch('mymodule.date') as mock_date: + ... mock_date.today.return_value = date(2010, 10, 8) + ... mock_date.side_effect = lambda *args, **kw: date(*args, **kw) + ... + ... assert mymodule.date.today() == date(2010, 10, 8) + ... assert mymodule.date(2009, 6, 8) == date(2009, 6, 8) + ... Note that we don't patch :class:`datetime.date` globally, we patch ``date`` in the module that *uses* it. See :ref:`where to patch `. @@ -658,22 +651,25 @@ various forms) as a class decorator. This applies the patches to all test methods on the class. A test method is identified by methods whose names start with ``test``: - >>> @patch('mymodule.SomeClass') - ... class MyTest(unittest.TestCase): - ... - ... def test_one(self, MockSomeClass): - ... self.assertIs(mymodule.SomeClass, MockSomeClass) - ... - ... def test_two(self, MockSomeClass): - ... self.assertIs(mymodule.SomeClass, MockSomeClass) - ... - ... def not_a_test(self): - ... return 'something' - ... - >>> MyTest('test_one').test_one() - >>> MyTest('test_two').test_two() - >>> MyTest('test_two').not_a_test() - 'something' +.. doctest:: + :options: +SKIP + + >>> @patch('mymodule.SomeClass') + >>> class MyTest(unittest.TestCase): + ... + ... def test_one(self, MockSomeClass): + ... self.assertIs(mymodule.SomeClass, MockSomeClass) + ... + ... def test_two(self, MockSomeClass): + ... self.assertIs(mymodule.SomeClass, MockSomeClass) + ... + ... def not_a_test(self): + ... return 'something' + ... + >>> MyTest('test_one').test_one() + >>> MyTest('test_two').test_two() + >>> MyTest('test_two').not_a_test() + 'something' An alternative way of managing patches is to use the :ref:`start-and-stop`. These allow you to move the patching into your ``setUp`` and ``tearDown`` methods. @@ -689,8 +685,7 @@ These allow you to move the patching into your ``setUp`` and ``tearDown`` method ... def tearDown(self): ... self.patcher.stop() ... - >>> MyTest('test_foo').run() - + >>> MyTest('test_foo').run() # doctest: +SKIP If you use this technique you must ensure that the patching is "undone" by calling ``stop``. This can be fiddlier than you might think, because if an @@ -706,8 +701,7 @@ exception is raised in the setUp then tearDown is not called. ... def test_foo(self): ... self.assertIs(mymodule.foo, self.mock_foo) ... - >>> MyTest('test_foo').run() - + >>> MyTest('test_foo').run() # doctest: +SKIP Mocking Unbound Methods @@ -813,17 +807,20 @@ defined in 'mymodule':: When we try to test that ``grob`` calls ``frob`` with the correct argument look what happens: - >>> with patch('mymodule.frob') as mock_frob: - ... val = {6} - ... mymodule.grob(val) - ... - >>> val - set() - >>> mock_frob.assert_called_with({6}) - Traceback (most recent call last): - ... - AssertionError: Expected: (({6},), {}) - Called with: ((set(),), {}) +.. doctest:: + :options: +SKIP + + >>> with patch('mymodule.frob') as mock_frob: + ... val = {6} + ... mymodule.grob(val) + ... + >>> val + set() + >>> mock_frob.assert_called_with({6}) + Traceback (most recent call last): + ... + AssertionError: Expected: (({6},), {}) + Called with: ((set(),), {}) One possibility would be for mock to copy the arguments you pass in. This could then cause problems if you do assertions that rely on object identity @@ -837,26 +834,29 @@ example I'm using *another* mock to store the arguments so that I can use the mock methods for doing the assertion. Again a helper function sets this up for me. - >>> from copy import deepcopy - >>> from unittest.mock import Mock, patch, DEFAULT - >>> def copy_call_args(mock): - ... new_mock = Mock() - ... def side_effect(*args, **kwargs): - ... args = deepcopy(args) - ... kwargs = deepcopy(kwargs) - ... new_mock(*args, **kwargs) - ... return DEFAULT - ... mock.side_effect = side_effect - ... return new_mock - ... - >>> with patch('mymodule.frob') as mock_frob: - ... new_mock = copy_call_args(mock_frob) - ... val = {6} - ... mymodule.grob(val) - ... - >>> new_mock.assert_called_with({6}) - >>> new_mock.call_args - call({6}) +.. doctest:: + :options: +SKIP + + >>> from copy import deepcopy + >>> from unittest.mock import Mock, patch, DEFAULT + >>> def copy_call_args(mock): + ... new_mock = Mock() + ... def side_effect(*args, **kwargs): + ... args = deepcopy(args) + ... kwargs = deepcopy(kwargs) + ... new_mock(*args, **kwargs) + ... return DEFAULT + ... mock.side_effect = side_effect + ... return new_mock + ... + >>> with patch('mymodule.frob') as mock_frob: + ... new_mock = copy_call_args(mock_frob) + ... val = {6} + ... mymodule.grob(val) + ... + >>> new_mock.assert_called_with({6}) + >>> new_mock.call_args + call({6}) ``copy_call_args`` is called with the mock that will be called. It returns a new mock that we do the assertion on. The ``side_effect`` function makes a copy of @@ -914,46 +914,51 @@ Using patch as a context manager is nice, but if you do multiple patches you can end up with nested with statements indenting further and further to the right: - >>> class MyTest(unittest.TestCase): - ... - ... def test_foo(self): - ... with patch('mymodule.Foo') as mock_foo: - ... with patch('mymodule.Bar') as mock_bar: - ... with patch('mymodule.Spam') as mock_spam: - ... assert mymodule.Foo is mock_foo - ... assert mymodule.Bar is mock_bar - ... assert mymodule.Spam is mock_spam - ... - >>> original = mymodule.Foo - >>> MyTest('test_foo').test_foo() - >>> assert mymodule.Foo is original +.. doctest:: + :options: +SKIP + + >>> class MyTest(unittest.TestCase): + ... + ... def test_foo(self): + ... with patch('mymodule.Foo') as mock_foo: + ... with patch('mymodule.Bar') as mock_bar: + ... with patch('mymodule.Spam') as mock_spam: + ... assert mymodule.Foo is mock_foo + ... assert mymodule.Bar is mock_bar + ... assert mymodule.Spam is mock_spam + ... + >>> original = mymodule.Foo + >>> MyTest('test_foo').test_foo() + >>> assert mymodule.Foo is original With unittest ``cleanup`` functions and the :ref:`start-and-stop` we can achieve the same effect without the nested indentation. A simple helper method, ``create_patch``, puts the patch in place and returns the created mock for us: - >>> class MyTest(unittest.TestCase): - ... - ... def create_patch(self, name): - ... patcher = patch(name) - ... thing = patcher.start() - ... self.addCleanup(patcher.stop) - ... return thing - ... - ... def test_foo(self): - ... mock_foo = self.create_patch('mymodule.Foo') - ... mock_bar = self.create_patch('mymodule.Bar') - ... mock_spam = self.create_patch('mymodule.Spam') - ... - ... assert mymodule.Foo is mock_foo - ... assert mymodule.Bar is mock_bar - ... assert mymodule.Spam is mock_spam - ... - >>> original = mymodule.Foo - >>> MyTest('test_foo').run() - - >>> assert mymodule.Foo is original +.. doctest:: + :options: +SKIP + + >>> class MyTest(unittest.TestCase): + ... + ... def create_patch(self, name): + ... patcher = patch(name) + ... thing = patcher.start() + ... self.addCleanup(patcher.stop) + ... return thing + ... + ... def test_foo(self): + ... mock_foo = self.create_patch('mymodule.Foo') + ... mock_bar = self.create_patch('mymodule.Bar') + ... mock_spam = self.create_patch('mymodule.Spam') + ... + ... assert mymodule.Foo is mock_foo + ... assert mymodule.Bar is mock_bar + ... assert mymodule.Spam is mock_spam + ... + >>> original = mymodule.Foo + >>> MyTest('test_foo').run() + >>> assert mymodule.Foo is original Mocking a dictionary with MagicMock @@ -1129,6 +1134,7 @@ Here's an example that mocks out the 'fooble' module. ... fooble.blob() ... + >>> import sys >>> assert 'fooble' not in sys.modules >>> mock.blob.assert_called_once_with() @@ -1193,21 +1199,24 @@ If ``patch`` is creating, and putting in place, your mocks then you can attach them to a manager mock using the :meth:`~Mock.attach_mock` method. After attaching calls will be recorded in ``mock_calls`` of the manager. - >>> manager = MagicMock() - >>> with patch('mymodule.Class1') as MockClass1: - ... with patch('mymodule.Class2') as MockClass2: - ... manager.attach_mock(MockClass1, 'MockClass1') - ... manager.attach_mock(MockClass2, 'MockClass2') - ... MockClass1().foo() - ... MockClass2().bar() - ... - - - >>> manager.mock_calls - [call.MockClass1(), - call.MockClass1().foo(), - call.MockClass2(), - call.MockClass2().bar()] +.. doctest:: + :options: +SKIP + + >>> manager = MagicMock() + >>> with patch('mymodule.Class1') as MockClass1: + ... with patch('mymodule.Class2') as MockClass2: + ... manager.attach_mock(MockClass1, 'MockClass1') + ... manager.attach_mock(MockClass2, 'MockClass2') + ... MockClass1().foo() + ... MockClass2().bar() + ... + + + >>> manager.mock_calls + [call.MockClass1(), + call.MockClass1().foo(), + call.MockClass2(), + call.MockClass2().bar()] If many calls have been made, but you're only interested in a particular sequence of them then an alternative is to use the diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index f0e5f1a125bf0e2..a53b8dbe620c1f0 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -13,24 +13,8 @@ .. testsetup:: import unittest - import unittest_mock.package.module as module - import unittest_mock.package as package - - # This allows us to import unittest_mock.package.module as - # ``import module`` and unittest_mock.package as ``import package`` - import sys - sys.modules['module'] = module - sys.modules['package'] = package - -.. testcleanup:: - - for module in [ - 'unittest_mock', - 'unittest_mock.package', - 'unittest_mock.package.module', - 'package', - 'module']: - del sys.modules[module] + from unittest.mock import MagicMock, PropertyMock, patch + from urllib import request **Source code:** :source:`Lib/unittest/mock.py` @@ -69,16 +53,15 @@ methods as you access them and store details of how they have been used. You can configure them, to specify return values or limit what attributes are available, and then make assertions about how they have been used: - >>> from unittest.mock import MagicMock - >>> class ProductionClass: - ... def method(self): - ... pass - ... - >>> thing = ProductionClass() - >>> thing.method = MagicMock(return_value=3) - >>> thing.method(3, 4, 5, key='value') - 3 - >>> thing.method.assert_called_with(3, 4, 5, key='value') +.. doctest:: + :options: +SKIP + + >>> from unittest.mock import MagicMock + >>> thing = ProductionClass() + >>> thing.method = MagicMock(return_value=3) + >>> thing.method(3, 4, 5, key='value') + 3 + >>> thing.method.assert_called_with(3, 4, 5, key='value') :attr:`side_effect` allows you to perform side effects, including raising an exception when a mock is called: @@ -110,18 +93,21 @@ The :func:`patch` decorator / context manager makes it easy to mock classes or objects in a module under test. The object you specify will be replaced with a mock (or other object) during the test and restored when the test ends: - >>> from unittest.mock import patch - >>> @patch('module.ClassName2') - ... @patch('module.ClassName1') - ... def test(MockClass1, MockClass2): - ... module.ClassName1() - ... module.ClassName2() - ... assert MockClass1 is module.ClassName1 - ... assert MockClass2 is module.ClassName2 - ... assert MockClass1.called - ... assert MockClass2.called - ... - >>> test() +.. doctest:: + :options: +SKIP + + >>> from unittest.mock import patch + >>> @patch('module.ClassName2') + ... @patch('module.ClassName1') + ... def test(MockClass1, MockClass2): + ... module.ClassName1() + ... module.ClassName2() + ... assert MockClass1 is module.ClassName1 + ... assert MockClass2 is module.ClassName2 + ... assert MockClass1.called + ... assert MockClass2.called + ... + >>> test() .. note:: @@ -137,11 +123,14 @@ mock (or other object) during the test and restored when the test ends: As well as a decorator :func:`patch` can be used as a context manager in a with statement: - >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method: - ... thing = ProductionClass() - ... thing.method(1, 2, 3) - ... - >>> mock_method.assert_called_once_with(1, 2, 3) +.. doctest:: + :options: +SKIP + + >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method: + ... thing = ProductionClass() + ... thing.method(1, 2, 3) + ... + >>> mock_method.assert_called_once_with(1, 2, 3) There is also :func:`patch.dict` for setting values in a dictionary just @@ -740,19 +729,15 @@ the *new_callable* argument to :func:`patch`. Mock objects that use a class or an instance as a :attr:`spec` or :attr:`spec_set` are able to pass :func:`isinstance` tests: - >>> class SomeClass: - ... def static_method(par): - ... pass - ... @classmethod - ... def class_method(cls, par): - ... pass - ... - >>> mock = Mock(spec=SomeClass) - >>> isinstance(mock, SomeClass) - True - >>> mock = Mock(spec_set=SomeClass()) - >>> isinstance(mock, SomeClass) - True +.. doctest:: + :options: +SKIP + + >>> mock = Mock(spec=SomeClass) + >>> isinstance(mock, SomeClass) + True + >>> mock = Mock(spec_set=SomeClass()) + >>> isinstance(mock, SomeClass) + True The :class:`Mock` classes have support for mocking magic methods. See :ref:`magic methods ` for the full details. @@ -814,24 +799,27 @@ apply to method calls on the mock object. Fetching a :class:`PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. - >>> from unittest.mock import PropertyMock - >>> class Foo: - ... @property - ... def foo(self): - ... return 'something' - ... @foo.setter - ... def foo(self, value): - ... pass - ... - >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo: - ... mock_foo.return_value = 'mockity-mock' - ... this_foo = Foo() - ... print(this_foo.foo) - ... this_foo.foo = 6 - ... - mockity-mock - >>> mock_foo.mock_calls - [call(), call(6)] + .. doctest:: + :options: +SKIP + + >>> from unittest.mock import PropertyMock + >>> class Foo: + ... @property + ... def foo(self): + ... return 'something' + ... @foo.setter + ... def foo(self, value): + ... pass + ... + >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo: + ... mock_foo.return_value = 'mockity-mock' + ... this_foo = Foo() + ... print(this_foo.foo) + ... this_foo.foo = 6 + ... + mockity-mock + >>> mock_foo.mock_calls + [call(), call(6)] Because of the way mock attributes are stored you can't directly attach a :class:`PropertyMock` to a mock object. Instead you can attach it to the mock type @@ -1042,18 +1030,21 @@ Mocks created for you by :func:`patch` are automatically given names. To attach mocks that have names to a parent you use the :meth:`~Mock.attach_mock` method: - >>> thing1 = object() - >>> thing2 = object() - >>> parent = MagicMock() - >>> with patch('__main__.thing1', return_value=None) as child1: - ... with patch('__main__.thing2', return_value=None) as child2: - ... parent.attach_mock(child1, 'child1') - ... parent.attach_mock(child2, 'child2') - ... child1('one') - ... child2('two') - ... - >>> parent.mock_calls - [call.child1('one'), call.child2('two')] +.. doctest:: + :options: +SKIP + + >>> thing1 = object() + >>> thing2 = object() + >>> parent = MagicMock() + >>> with patch('__main__.thing1', return_value=None) as child1: + ... with patch('__main__.thing2', return_value=None) as child2: + ... parent.attach_mock(child1, 'child1') + ... parent.attach_mock(child2, 'child2') + ... child1('one') + ... child2('two') + ... + >>> parent.mock_calls + [call.child1('one'), call.child2('two')] .. [#] The only exceptions are magic methods and attributes (those that have @@ -1158,12 +1149,15 @@ patch :func:`patch` as function decorator, creating the mock for you and passing it into the decorated function: - >>> @patch('__main__.SomeClass') - ... def function(normal_argument, mock_class): - ... print(mock_class is SomeClass) - ... - >>> function(None) - True +.. doctest:: + :options: +SKIP + + >>> @patch('__main__.SomeClass') + ... def function(normal_argument, mock_class): + ... print(mock_class is SomeClass) + ... + >>> function(None) + True Patching a class replaces the class with a :class:`MagicMock` *instance*. If the class is instantiated in the code under test then it will be the @@ -1176,40 +1170,49 @@ can set the *return_value* to be anything you want. To configure return values on methods of *instances* on the patched class you must do this on the :attr:`return_value`. For example: - >>> class Class: - ... def method(self): - ... pass - ... - >>> with patch('__main__.Class') as MockClass: - ... instance = MockClass.return_value - ... instance.method.return_value = 'foo' - ... assert Class() is instance - ... assert Class().method() == 'foo' - ... +.. doctest:: + :options: +SKIP + + >>> class Class: + ... def method(self): + ... pass + ... + >>> with patch('__main__.Class') as MockClass: + ... instance = MockClass.return_value + ... instance.method.return_value = 'foo' + ... assert Class() is instance + ... assert Class().method() == 'foo' + ... If you use *spec* or *spec_set* and :func:`patch` is replacing a *class*, then the return value of the created mock will have the same spec. - >>> Original = Class - >>> patcher = patch('__main__.Class', spec=True) - >>> MockClass = patcher.start() - >>> instance = MockClass() - >>> assert isinstance(instance, Original) - >>> patcher.stop() +.. doctest:: + :options: +SKIP + + >>> Original = Class + >>> patcher = patch('__main__.Class', spec=True) + >>> MockClass = patcher.start() + >>> instance = MockClass() + >>> assert isinstance(instance, Original) + >>> patcher.stop() The *new_callable* argument is useful where you want to use an alternative class to the default :class:`MagicMock` for the created mock. For example, if you wanted a :class:`NonCallableMock` to be used: - >>> from unittest.mock import NonCallableMock - >>> thing = object() - >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing: - ... assert thing is mock_thing - ... thing() - ... - Traceback (most recent call last): - ... - TypeError: 'NonCallableMock' object is not callable +.. doctest:: + :options: +SKIP + + >>> from unittest.mock import NonCallableMock + >>> thing = object() + >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing: + ... assert thing is mock_thing + ... thing() + ... + Traceback (most recent call last): + ... + TypeError: 'NonCallableMock' object is not callable Another use case might be to replace an object with an :class:`io.StringIO` instance: @@ -1229,12 +1232,15 @@ you need to do is to configure the mock. Some of that configuration can be done in the call to patch. Any arbitrary keywords you pass into the call will be used to set attributes on the created mock: - >>> patcher = patch('__main__.thing', first='one', second='two') - >>> mock_thing = patcher.start() - >>> mock_thing.first - 'one' - >>> mock_thing.second - 'two' +.. doctest:: + :options: +SKIP + + >>> patcher = patch('__main__.thing', first='one', second='two') + >>> mock_thing = patcher.start() + >>> mock_thing.first + 'one' + >>> mock_thing.second + 'two' As well as attributes on the created mock attributes, like the :attr:`~Mock.return_value` and :attr:`~Mock.side_effect`, of child mocks can @@ -1242,15 +1248,18 @@ also be configured. These aren't syntactically valid to pass in directly as keyword arguments, but a dictionary with these as keys can still be expanded into a :func:`patch` call using ``**``: - >>> config = {'method.return_value': 3, 'other.side_effect': KeyError} - >>> patcher = patch('__main__.thing', **config) - >>> mock_thing = patcher.start() - >>> mock_thing.method() - 3 - >>> mock_thing.other() - Traceback (most recent call last): - ... - KeyError +.. doctest:: + :options: +SKIP + + >>> config = {'method.return_value': 3, 'other.side_effect': KeyError} + >>> patcher = patch('__main__.thing', **config) + >>> mock_thing = patcher.start() + >>> mock_thing.method() + 3 + >>> mock_thing.other() + Traceback (most recent call last): + ... + KeyError patch.object @@ -1278,12 +1287,15 @@ When calling with the two argument form you omit the replacement object, and a mock is created for you and passed in as an extra argument to the decorated function: - >>> @patch.object(SomeClass, 'class_method') - ... def test(mock_method): - ... SomeClass.class_method(3) - ... mock_method.assert_called_with(3) - ... - >>> test() +.. doctest:: + :options: +SKIP + + >>> @patch.object(SomeClass, 'class_method') + ... def test(mock_method): + ... SomeClass.class_method(3) + ... mock_method.assert_called_with(3) + ... + >>> test() *spec*, *create* and the other arguments to :func:`patch.object` have the same meaning as they do for :func:`patch`. @@ -1401,37 +1413,45 @@ If you want :func:`patch.multiple` to create mocks for you, then you can use :data:`DEFAULT` as the value. If you use :func:`patch.multiple` as a decorator then the created mocks are passed into the decorated function by keyword. - >>> thing = object() - >>> other = object() +.. doctest:: + :options: +SKIP - >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) - ... def test_function(thing, other): - ... assert isinstance(thing, MagicMock) - ... assert isinstance(other, MagicMock) - ... - >>> test_function() + >>> thing = object() + >>> other = object() + >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) + ... def test_function(thing, other): + ... assert isinstance(thing, MagicMock) + ... assert isinstance(other, MagicMock) + ... + >>> test_function() :func:`patch.multiple` can be nested with other ``patch`` decorators, but put arguments passed by keyword *after* any of the standard arguments created by :func:`patch`: - >>> @patch('sys.exit') - ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) - ... def test_function(mock_exit, other, thing): - ... assert 'other' in repr(other) - ... assert 'thing' in repr(thing) - ... assert 'exit' in repr(mock_exit) - ... - >>> test_function() +.. doctest:: + :options: +SKIP + + >>> @patch('sys.exit') + ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) + ... def test_function(mock_exit, other, thing): + ... assert 'other' in repr(other) + ... assert 'thing' in repr(thing) + ... assert 'exit' in repr(mock_exit) + ... + >>> test_function() If :func:`patch.multiple` is used as a context manager, the value returned by the context manger is a dictionary where created mocks are keyed by name: - >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values: - ... assert 'other' in repr(values['other']) - ... assert 'thing' in repr(values['thing']) - ... assert values['thing'] is thing - ... assert values['other'] is other - ... +.. doctest:: + :options: +SKIP + + >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values: + ... assert 'other' in repr(values['other']) + ... assert 'thing' in repr(values['thing']) + ... assert values['thing'] is thing + ... assert values['other'] is other + ... .. _start-and-stop: @@ -1450,15 +1470,18 @@ call :meth:`start` to put the patch in place and :meth:`stop` to undo it. If you are using :func:`patch` to create a mock for you then it will be returned by the call to ``patcher.start``. - >>> patcher = patch('package.module.ClassName') - >>> from package import module - >>> original = module.ClassName - >>> new_mock = patcher.start() - >>> assert module.ClassName is not original - >>> assert module.ClassName is new_mock - >>> patcher.stop() - >>> assert module.ClassName is original - >>> assert module.ClassName is not new_mock +.. doctest:: + :options: +SKIP + + >>> patcher = patch('package.module.ClassName') + >>> from package import module + >>> original = module.ClassName + >>> new_mock = patcher.start() + >>> assert module.ClassName is not original + >>> assert module.ClassName is new_mock + >>> patcher.stop() + >>> assert module.ClassName is original + >>> assert module.ClassName is not new_mock A typical use case for this might be for doing multiple patches in the ``setUp`` @@ -1479,8 +1502,7 @@ method of a :class:`TestCase`: ... assert package.module.Class1 is self.MockClass1 ... assert package.module.Class2 is self.MockClass2 ... - >>> MyTest('test_something').run() - + >>> MyTest('test_something').run() # doctest: +SKIP .. caution:: @@ -1517,20 +1539,16 @@ patch builtins You can patch any builtins within a module. The following example patches builtin :func:`ord`: -.. testsetup:: ord - - from builtins import ord - from unittest.mock import patch - -.. doctest:: ord +.. doctest:: + :options: +SKIP - >>> @patch('__main__.ord') - ... def test(mock_ord): - ... mock_ord.return_value = 101 - ... print(ord('c')) - ... - >>> test() - 101 + >>> @patch('__main__.ord') + ... def test(mock_ord): + ... mock_ord.return_value = 101 + ... print(ord('c')) + ... + >>> test() + 101 TEST_PREFIX @@ -1544,34 +1562,26 @@ start with ``'test'`` as being test methods. This is the same way that the It is possible that you want to use a different prefix for your tests. You can inform the patchers of the different prefix by setting ``patch.TEST_PREFIX``: -.. testsetup:: test-prefix - - from unittest.mock import patch - TEST_PREFIX = patch.TEST_PREFIX - -.. testcleanup:: test-prefix - - patch.TEST_PREFIX = TEST_PREFIX - -.. doctest:: test-prefix +.. doctest:: + :options: +SKIP - >>> patch.TEST_PREFIX = 'foo' - >>> value = 3 - >>> - >>> @patch('__main__.value', 'not three') - ... class Thing: - ... def foo_one(self): - ... print(value) - ... def foo_two(self): - ... print(value) - ... - >>> - >>> Thing().foo_one() - not three - >>> Thing().foo_two() - not three - >>> value - 3 + >>> patch.TEST_PREFIX = 'foo' + >>> value = 3 + >>> + >>> @patch('__main__.value', 'not three') + ... class Thing: + ... def foo_one(self): + ... print(value) + ... def foo_two(self): + ... print(value) + ... + >>> + >>> Thing().foo_one() + not three + >>> Thing().foo_two() + not three + >>> value + 3 Nesting Patch Decorators @@ -1582,18 +1592,21 @@ decorators. You can stack up multiple patch decorators using this pattern: - >>> @patch.object(SomeClass, 'class_method') - ... @patch.object(SomeClass, 'static_method') - ... def test(mock1, mock2): - ... assert SomeClass.static_method is mock1 - ... assert SomeClass.class_method is mock2 - ... SomeClass.static_method('foo') - ... SomeClass.class_method('bar') - ... return mock1, mock2 - ... - >>> mock1, mock2 = test() - >>> mock1.assert_called_once_with('foo') - >>> mock2.assert_called_once_with('bar') +.. doctest:: + :options: +SKIP + + >>> @patch.object(SomeClass, 'class_method') + ... @patch.object(SomeClass, 'static_method') + ... def test(mock1, mock2): + ... assert SomeClass.static_method is mock1 + ... assert SomeClass.class_method is mock2 + ... SomeClass.static_method('foo') + ... SomeClass.class_method('bar') + ... return mock1, mock2 + ... + >>> mock1, mock2 = test() + >>> mock1.assert_called_once_with('foo') + >>> mock2.assert_called_once_with('bar') Note that the decorators are applied from the bottom upwards. This is the @@ -1902,13 +1915,16 @@ creating and testing the identity of objects like this. In this example we monkey patch ``method`` to return ``sentinel.some_object``: - >>> real = ProductionClass() - >>> real.method = Mock(name="method") - >>> real.method.return_value = sentinel.some_object - >>> result = real.method() - >>> assert result is sentinel.some_object - >>> sentinel.some_object - sentinel.some_object +.. doctest:: + :options: +SKIP + + >>> real = ProductionClass() + >>> real.method = Mock(name="method") + >>> real.method.return_value = sentinel.some_object + >>> result = real.method() + >>> assert result is sentinel.some_object + >>> sentinel.some_object + sentinel.some_object DEFAULT @@ -2090,20 +2106,20 @@ yet: .. doctest:: :options: +NORMALIZE_WHITESPACE - >>> dir(Mock()) - ['assert_any_call', - 'assert_called', - 'assert_called_once', - 'assert_called_once_with', - 'assert_called_with', - ... - >>> from urllib import request - >>> dir(Mock(spec=request)) - ['AbstractBasicAuthHandler', - 'AbstractDigestAuthHandler', - 'AbstractHTTPHandler', - 'BaseHandler', - ... + >>> dir(Mock()) + ['assert_any_call', + 'assert_called', + 'assert_called_once', + 'assert_called_once_with', + 'assert_called_with', + ... + >>> from urllib import request + >>> dir(Mock(spec=request)) + ['AbstractBasicAuthHandler', + 'AbstractDigestAuthHandler', + 'AbstractHTTPHandler', + 'BaseHandler', + ... Many of the not-very-useful (private to :class:`Mock` rather than the thing being mocked) underscore and double underscore prefixed attributes have been @@ -2174,38 +2190,34 @@ The issue is that even if you mock out the call to :func:`open` it is the Mocking context managers with a :class:`MagicMock` is common enough and fiddly enough that a helper function is useful. -.. testsetup:: open - - from builtins import open - from unittest.mock import patch - -.. doctest:: open +.. doctest:: + :options: +SKIP - >>> from unittest.mock import mock_open - >>> m = mock_open() - >>> with patch('__main__.open', m): - ... with open('foo', 'w') as h: - ... h.write('some stuff') - ... - >>> m.mock_calls - [call('foo', 'w'), - call().__enter__(), - call().write('some stuff'), - call().__exit__(None, None, None)] - >>> m.assert_called_once_with('foo', 'w') - >>> handle = m() - >>> handle.write.assert_called_once_with('some stuff') + >>> m = mock_open() + >>> with patch('__main__.open', m): + ... with open('foo', 'w') as h: + ... h.write('some stuff') + ... + >>> m.mock_calls + [call('foo', 'w'), + call().__enter__(), + call().write('some stuff'), + call().__exit__(None, None, None)] + >>> m.assert_called_once_with('foo', 'w') + >>> handle = m() + >>> handle.write.assert_called_once_with('some stuff') And for reading files: -.. doctest:: open +.. doctest:: + :options: +SKIP - >>> with patch('__main__.open', mock_open(read_data='bibble')) as m: - ... with open('foo') as h: - ... result = h.read() - ... - >>> m.assert_called_once_with('foo') - >>> assert result == 'bibble' + >>> with patch('__main__.open', mock_open(read_data='bibble')) as m: + ... with open('foo') as h: + ... result = h.read() + ... + >>> m.assert_called_once_with('foo') + >>> assert result == 'bibble' .. _auto-speccing: @@ -2293,13 +2305,16 @@ hit. Here's an example of it in use: - >>> from urllib import request - >>> patcher = patch('__main__.request', autospec=True) - >>> mock_request = patcher.start() - >>> request is mock_request - True - >>> mock_request.Request - +.. doctest:: + :options: +SKIP + + >>> from urllib import request + >>> patcher = patch('__main__.request', autospec=True) + >>> mock_request = patcher.start() + >>> request is mock_request + True + >>> mock_request.Request + You can see that :class:`request.Request` has a spec. :class:`request.Request` takes two arguments in the constructor (one of which is *self*). Here's what happens if @@ -2313,21 +2328,27 @@ we try to call it incorrectly: The spec also applies to instantiated classes (i.e. the return value of specced mocks): - >>> req = request.Request('foo') - >>> req - +.. doctest:: + :options: +SKIP + + >>> req = request.Request('foo') + >>> req + :class:`Request` objects are not callable, so the return value of instantiating our mocked out :class:`request.Request` is a non-callable mock. With the spec in place any typos in our asserts will raise the correct error: - >>> req.add_header('spam', 'eggs') - - >>> req.add_header.assret_called_with - Traceback (most recent call last): - ... - AttributeError: Mock object has no attribute 'assret_called_with' - >>> req.add_header.assert_called_with('spam', 'eggs') +.. doctest:: + :options: +SKIP + + >>> req.add_header('spam', 'eggs') + + >>> req.add_header.assret_called_with + Traceback (most recent call last): + ... + AttributeError: Mock object has no attribute 'assret_called_with' + >>> req.add_header.assert_called_with('spam', 'eggs') In many cases you will just be able to add ``autospec=True`` to your existing :func:`patch` calls and then be protected against bugs due to typos and api @@ -2355,17 +2376,20 @@ created in the :meth:`__init__` method and not to exist on the class at all. *autospec* can't know about any dynamically created attributes and restricts the api to visible attributes. - >>> class Something: - ... def __init__(self): - ... self.a = 33 - ... - >>> with patch('__main__.Something', autospec=True): - ... thing = Something() - ... thing.a - ... - Traceback (most recent call last): - ... - AttributeError: Mock object has no attribute 'a' +.. doctest:: + :options: +SKIP + + >>> class Something: + ... def __init__(self): + ... self.a = 33 + ... + >>> with patch('__main__.Something', autospec=True): + ... thing = Something() + ... thing.a + ... + Traceback (most recent call last): + ... + AttributeError: Mock object has no attribute 'a' There are a few different ways of resolving this problem. The easiest, but not necessarily the least annoying, way is to simply set the required @@ -2373,23 +2397,29 @@ attributes on the mock after creation. Just because *autospec* doesn't allow you to fetch attributes that don't exist on the spec it doesn't prevent you setting them: - >>> with patch('__main__.Something', autospec=True): - ... thing = Something() - ... thing.a = 33 - ... +.. doctest:: + :options: +SKIP + + >>> with patch('__main__.Something', autospec=True): + ... thing = Something() + ... thing.a = 33 + ... There is a more aggressive version of both *spec* and *autospec* that *does* prevent you setting non-existent attributes. This is useful if you want to ensure your code only *sets* valid attributes too, but obviously it prevents this particular scenario: - >>> with patch('__main__.Something', autospec=True, spec_set=True): - ... thing = Something() - ... thing.a = 33 +.. doctest:: + :options: +SKIP + + >>> with patch('__main__.Something', autospec=True, spec_set=True): + ... thing = Something() + ... thing.a = 33 + ... + Traceback (most recent call last): ... - Traceback (most recent call last): - ... - AttributeError: Mock object has no attribute 'a' + AttributeError: Mock object has no attribute 'a' Probably the best way of solving the problem is to add class attributes as default values for instance members initialised in :meth:`__init__`. Note that if @@ -2424,17 +2454,21 @@ production class. Both of these require you to use an alternative object as the spec. Thankfully :func:`patch` supports this - you can simply pass the alternative object as the *autospec* argument: - >>> class Something: - ... def __init__(self): - ... self.a = 33 - ... - >>> class SomethingForTest(Something): - ... a = 33 - ... - >>> p = patch('__main__.Something', autospec=SomethingForTest) - >>> mock = p.start() - >>> mock.a - +.. doctest:: + :options: +SKIP + + + >>> class Something: + ... def __init__(self): + ... self.a = 33 + ... + >>> class SomethingForTest(Something): + ... a = 33 + ... + >>> p = patch('__main__.Something', autospec=SomethingForTest) + >>> mock = p.start() + >>> mock.a + .. [#] This only applies to classes or already instantiated objects. Calling From fdb8c4ee7fa8adf4f92ed2cc9ca6146b8826646d Mon Sep 17 00:00:00 2001 From: Marco Buttu Date: Thu, 11 May 2017 18:53:02 +0200 Subject: [PATCH 4/4] bpo-27200: align :options: to the code example. --- Doc/library/unittest.mock-examples.rst | 399 ++++++++------- Doc/library/unittest.mock.rst | 641 ++++++++++++------------- 2 files changed, 517 insertions(+), 523 deletions(-) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst index 138ddba403ec434..e1bcb50dbc57913 100644 --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -29,13 +29,12 @@ You might want to replace a method on an object to check that it is called with the correct arguments by another part of the system: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> from unittest.mock import MagicMock - >>> real = SomeClass() - >>> real.method = MagicMock(name='method') - >>> real.method(3, 4, 5, key='value') - + >>> real = SomeClass() + >>> real.method = MagicMock(name='method') + >>> real.method(3, 4, 5, key='value') + Once our mock has been used (``real.method`` in this example) it has methods and attributes that allow you to make assertions about how it has been used. @@ -112,18 +111,17 @@ mock. The ``Foo`` instance is the result of calling the mock, so it is configure by modifying the mock :attr:`~Mock.return_value`. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> def some_function(): - ... instance = mymodule.Foo() - ... return instance.method() - ... - >>> from unittest.mock import patch - >>> with patch('mymodule.Foo') as mock: - ... instance = mock.return_value - ... instance.method.return_value = 'the result' - ... result = some_function() - ... assert result == 'the result' + >>> def some_function(): + ... instance = module.Foo() + ... return instance.method() + ... + >>> with patch('module.Foo') as mock: + ... instance = mock.return_value + ... instance.method.return_value = 'the result' + ... result = some_function() + ... assert result == 'the result' Naming your mocks @@ -287,13 +285,13 @@ tests that use that class will start failing immediately without you having to instantiate the class in those tests. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> mock = Mock(spec=SomeClass) - >>> mock.old_method() - Traceback (most recent call last): - ... - AttributeError: object has no attribute 'old_method' + >>> mock = Mock(spec=SomeClass) + >>> mock.old_method() + Traceback (most recent call last): + ... + AttributeError: object has no attribute 'old_method' Using a specification also enables a smarter matching of calls made to the mock, regardless of whether some parameters were passed as positional or @@ -342,77 +340,76 @@ with. ``patch.object``: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> from unittest.mock import sentinel - >>> original = SomeClass.attribute - >>> @patch.object(SomeClass, 'attribute', sentinel.attribute) - ... def test(): - ... assert SomeClass.attribute == sentinel.attribute - ... - >>> test() - >>> assert SomeClass.attribute == original + >>> original = SomeClass.attribute + >>> @patch.object(SomeClass, 'attribute', sentinel.attribute) + ... def test(): + ... assert SomeClass.attribute == sentinel.attribute + ... + >>> test() + >>> assert SomeClass.attribute == original - >>> @patch('package.module.attribute', sentinel.attribute) - ... def test(): - ... from package.module import attribute - ... assert attribute is sentinel.attribute - ... - >>> test() + >>> @patch('package.module.attribute', sentinel.attribute) + ... def test(): + ... from package.module import attribute + ... assert attribute is sentinel.attribute + ... + >>> test() If you are patching a module (including :mod:`builtins`) then use :func:`patch` instead of :func:`patch.object`: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> mock = MagicMock(return_value=sentinel.file_handle) - >>> with patch('builtins.open', mock): - ... handle = open('filename', 'r') - ... - >>> mock.assert_called_with('filename', 'r') - >>> assert handle == sentinel.file_handle, "incorrect file handle returned" + >>> mock = MagicMock(return_value=sentinel.file_handle) + >>> with patch('builtins.open', mock): + ... handle = open('filename', 'r') + ... + >>> mock.assert_called_with('filename', 'r') + >>> assert handle == sentinel.file_handle, "incorrect file handle returned" The module name can be 'dotted', in the form ``package.module`` if needed: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> @patch('package.module.ClassName.attribute', sentinel.attribute) - ... def test(): - ... from package.module import ClassName - ... assert ClassName.attribute == sentinel.attribute - ... - >>> test() + >>> @patch('package.module.ClassName.attribute', sentinel.attribute) + ... def test(): + ... from package.module import ClassName + ... assert ClassName.attribute == sentinel.attribute + ... + >>> test() A nice pattern is to actually decorate test methods themselves: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class MyTest(unittest.TestCase): - ... @patch.object(SomeClass, 'attribute', sentinel.attribute) - ... def test_something(self): - ... self.assertEqual(SomeClass.attribute, sentinel.attribute) - ... - >>> original = SomeClass.attribute - >>> MyTest('test_something').test_something() - >>> assert SomeClass.attribute == original + >>> class MyTest(unittest.TestCase): + ... @patch.object(SomeClass, 'attribute', sentinel.attribute) + ... def test_something(self): + ... self.assertEqual(SomeClass.attribute, sentinel.attribute) + ... + >>> original = SomeClass.attribute + >>> MyTest('test_something').test_something() + >>> assert SomeClass.attribute == original If you want to patch with a Mock, you can use :func:`patch` with only one argument (or :func:`patch.object` with two arguments). The mock will be created for you and passed into the test function / method: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class MyTest(unittest.TestCase): - ... @patch.object(SomeClass, 'static_method') - ... def test_something(self, mock_method): - ... SomeClass.static_method() - ... mock_method.assert_called_with() - ... - >>> MyTest('test_something').test_something() + >>> class MyTest(unittest.TestCase): + ... @patch.object(SomeClass, 'static_method') + ... def test_something(self, mock_method): + ... SomeClass.static_method() + ... mock_method.assert_called_with() + ... + >>> MyTest('test_something').test_something() You can stack up multiple patch decorators using this pattern: @@ -495,14 +492,14 @@ testable way in the first place... So, suppose we have some code that looks a little bit like this: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class Something: - ... def __init__(self): - ... self.backend = BackendProvider() - ... def method(self): - ... response = self.backend.get_endpoint('foobar').create_call('spam', 'eggs').start_call() - ... # more code + >>> class Something: + ... def __init__(self): + ... self.backend = BackendProvider() + ... def method(self): + ... response = self.backend.get_endpoint('foobar').create_call('spam', 'eggs').start_call() + ... # more code Assuming that ``BackendProvider`` is already well tested, how do we test ``method()``? Specifically, we want to test that the code section ``# more @@ -525,22 +522,22 @@ We can do that in a slightly nicer way using the :meth:`~Mock.configure_mock` method to directly set the return value for us: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> something = Something() - >>> mock_response = Mock(spec=open) - >>> mock_backend = Mock() - >>> config = {'get_endpoint.return_value.create_call.return_value.start_call.return_value': mock_response} - >>> mock_backend.configure_mock(**config) + >>> something = Something() + >>> mock_response = Mock(spec=open) + >>> mock_backend = Mock() + >>> config = {'get_endpoint.return_value.create_call.return_value.start_call.return_value': mock_response} + >>> mock_backend.configure_mock(**config) With these we monkey patch the "mock backend" in place and can make the real call: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> something.backend = mock_backend - >>> something.method() + >>> something.backend = mock_backend + >>> something.method() Using :attr:`~Mock.mock_calls` we can check the chained call with a single assert. A chained call is several calls in one line of code, so there will be @@ -548,11 +545,11 @@ several entries in ``mock_calls``. We can use :meth:`call.call_list` to create this list of calls for us: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call() - >>> call_list = chained.call_list() - >>> assert mock_backend.mock_calls == call_list + >>> chained = call.get_endpoint('foobar').create_call('spam', 'eggs').start_call() + >>> call_list = chained.call_list() + >>> assert mock_backend.mock_calls == call_list Partial mocking @@ -574,16 +571,16 @@ a real date. When the mock date class is called a real date will be constructed and returned by ``side_effect``. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> from datetime import date - >>> with patch('mymodule.date') as mock_date: - ... mock_date.today.return_value = date(2010, 10, 8) - ... mock_date.side_effect = lambda *args, **kw: date(*args, **kw) - ... - ... assert mymodule.date.today() == date(2010, 10, 8) - ... assert mymodule.date(2009, 6, 8) == date(2009, 6, 8) - ... + >>> from datetime import date + >>> with patch('mymodule.date') as mock_date: + ... mock_date.today.return_value = date(2010, 10, 8) + ... mock_date.side_effect = lambda *args, **kw: date(*args, **kw) + ... + ... assert mymodule.date.today() == date(2010, 10, 8) + ... assert mymodule.date(2009, 6, 8) == date(2009, 6, 8) + ... Note that we don't patch :class:`datetime.date` globally, we patch ``date`` in the module that *uses* it. See :ref:`where to patch `. @@ -652,24 +649,24 @@ methods on the class. A test method is identified by methods whose names start with ``test``: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> @patch('mymodule.SomeClass') - >>> class MyTest(unittest.TestCase): - ... - ... def test_one(self, MockSomeClass): - ... self.assertIs(mymodule.SomeClass, MockSomeClass) - ... - ... def test_two(self, MockSomeClass): - ... self.assertIs(mymodule.SomeClass, MockSomeClass) - ... - ... def not_a_test(self): - ... return 'something' - ... - >>> MyTest('test_one').test_one() - >>> MyTest('test_two').test_two() - >>> MyTest('test_two').not_a_test() - 'something' + >>> @patch('mymodule.SomeClass') + ... class MyTest(TestCase): + ... + ... def test_one(self, MockSomeClass): + ... self.assertIs(mymodule.SomeClass, MockSomeClass) + ... + ... def test_two(self, MockSomeClass): + ... self.assertIs(mymodule.SomeClass, MockSomeClass) + ... + ... def not_a_test(self): + ... return 'something' + ... + >>> MyTest('test_one').test_one() + >>> MyTest('test_two').test_two() + >>> MyTest('test_two').not_a_test() + 'something' An alternative way of managing patches is to use the :ref:`start-and-stop`. These allow you to move the patching into your ``setUp`` and ``tearDown`` methods. @@ -808,19 +805,19 @@ When we try to test that ``grob`` calls ``frob`` with the correct argument look what happens: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> with patch('mymodule.frob') as mock_frob: - ... val = {6} - ... mymodule.grob(val) - ... - >>> val - set() - >>> mock_frob.assert_called_with({6}) - Traceback (most recent call last): - ... - AssertionError: Expected: (({6},), {}) - Called with: ((set(),), {}) + >>> with patch('mymodule.frob') as mock_frob: + ... val = {6} + ... mymodule.grob(val) + ... + >>> val + set() + >>> mock_frob.assert_called_with({6}) + Traceback (most recent call last): + ... + AssertionError: Expected: (({6},), {}) + Called with: ((set(),), {}) One possibility would be for mock to copy the arguments you pass in. This could then cause problems if you do assertions that rely on object identity @@ -835,28 +832,28 @@ mock methods for doing the assertion. Again a helper function sets this up for me. .. doctest:: - :options: +SKIP - - >>> from copy import deepcopy - >>> from unittest.mock import Mock, patch, DEFAULT - >>> def copy_call_args(mock): - ... new_mock = Mock() - ... def side_effect(*args, **kwargs): - ... args = deepcopy(args) - ... kwargs = deepcopy(kwargs) - ... new_mock(*args, **kwargs) - ... return DEFAULT - ... mock.side_effect = side_effect - ... return new_mock - ... - >>> with patch('mymodule.frob') as mock_frob: - ... new_mock = copy_call_args(mock_frob) - ... val = {6} - ... mymodule.grob(val) - ... - >>> new_mock.assert_called_with({6}) - >>> new_mock.call_args - call({6}) + :options: +SKIP + + >>> from copy import deepcopy + >>> from unittest.mock import Mock, patch, DEFAULT + >>> def copy_call_args(mock): + ... new_mock = Mock() + ... def side_effect(*args, **kwargs): + ... args = deepcopy(args) + ... kwargs = deepcopy(kwargs) + ... new_mock(*args, **kwargs) + ... return DEFAULT + ... mock.side_effect = side_effect + ... return new_mock + ... + >>> with patch('mymodule.frob') as mock_frob: + ... new_mock = copy_call_args(mock_frob) + ... val = {6} + ... mymodule.grob(val) + ... + >>> new_mock.assert_called_with({6}) + >>> new_mock.call_args + call({6}) ``copy_call_args`` is called with the mock that will be called. It returns a new mock that we do the assertion on. The ``side_effect`` function makes a copy of @@ -915,21 +912,21 @@ can end up with nested with statements indenting further and further to the right: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class MyTest(unittest.TestCase): - ... - ... def test_foo(self): - ... with patch('mymodule.Foo') as mock_foo: - ... with patch('mymodule.Bar') as mock_bar: - ... with patch('mymodule.Spam') as mock_spam: - ... assert mymodule.Foo is mock_foo - ... assert mymodule.Bar is mock_bar - ... assert mymodule.Spam is mock_spam - ... - >>> original = mymodule.Foo - >>> MyTest('test_foo').test_foo() - >>> assert mymodule.Foo is original + >>> class MyTest(unittest.TestCase): + ... + ... def test_foo(self): + ... with patch('mymodule.Foo') as mock_foo: + ... with patch('mymodule.Bar') as mock_bar: + ... with patch('mymodule.Spam') as mock_spam: + ... assert mymodule.Foo is mock_foo + ... assert mymodule.Bar is mock_bar + ... assert mymodule.Spam is mock_spam + ... + >>> original = mymodule.Foo + >>> MyTest('test_foo').test_foo() + >>> assert mymodule.Foo is original With unittest ``cleanup`` functions and the :ref:`start-and-stop` we can achieve the same effect without the nested indentation. A simple helper @@ -937,28 +934,28 @@ method, ``create_patch``, puts the patch in place and returns the created mock for us: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class MyTest(unittest.TestCase): - ... - ... def create_patch(self, name): - ... patcher = patch(name) - ... thing = patcher.start() - ... self.addCleanup(patcher.stop) - ... return thing - ... - ... def test_foo(self): - ... mock_foo = self.create_patch('mymodule.Foo') - ... mock_bar = self.create_patch('mymodule.Bar') - ... mock_spam = self.create_patch('mymodule.Spam') - ... - ... assert mymodule.Foo is mock_foo - ... assert mymodule.Bar is mock_bar - ... assert mymodule.Spam is mock_spam - ... - >>> original = mymodule.Foo - >>> MyTest('test_foo').run() - >>> assert mymodule.Foo is original + >>> class MyTest(unittest.TestCase): + ... + ... def create_patch(self, name): + ... patcher = patch(name) + ... thing = patcher.start() + ... self.addCleanup(patcher.stop) + ... return thing + ... + ... def test_foo(self): + ... mock_foo = self.create_patch('mymodule.Foo') + ... mock_bar = self.create_patch('mymodule.Bar') + ... mock_spam = self.create_patch('mymodule.Spam') + ... + ... assert mymodule.Foo is mock_foo + ... assert mymodule.Bar is mock_bar + ... assert mymodule.Spam is mock_spam + ... + >>> original = mymodule.Foo + >>> MyTest('test_foo').run() + >>> assert mymodule.Foo is original Mocking a dictionary with MagicMock @@ -1200,23 +1197,23 @@ them to a manager mock using the :meth:`~Mock.attach_mock` method. After attaching calls will be recorded in ``mock_calls`` of the manager. .. doctest:: - :options: +SKIP - - >>> manager = MagicMock() - >>> with patch('mymodule.Class1') as MockClass1: - ... with patch('mymodule.Class2') as MockClass2: - ... manager.attach_mock(MockClass1, 'MockClass1') - ... manager.attach_mock(MockClass2, 'MockClass2') - ... MockClass1().foo() - ... MockClass2().bar() - ... - - - >>> manager.mock_calls - [call.MockClass1(), - call.MockClass1().foo(), - call.MockClass2(), - call.MockClass2().bar()] + :options: +SKIP + + >>> manager = MagicMock() + >>> with patch('mymodule.Class1') as MockClass1: + ... with patch('mymodule.Class2') as MockClass2: + ... manager.attach_mock(MockClass1, 'MockClass1') + ... manager.attach_mock(MockClass2, 'MockClass2') + ... MockClass1().foo() + ... MockClass2().bar() + ... + + + >>> manager.mock_calls + [call.MockClass1(), + call.MockClass1().foo(), + call.MockClass2(), + call.MockClass2().bar()] If many calls have been made, but you're only interested in a particular sequence of them then an alternative is to use the diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index a53b8dbe620c1f0..c5e42b7abb41013 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -54,14 +54,14 @@ can configure them, to specify return values or limit what attributes are available, and then make assertions about how they have been used: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> from unittest.mock import MagicMock - >>> thing = ProductionClass() - >>> thing.method = MagicMock(return_value=3) - >>> thing.method(3, 4, 5, key='value') - 3 - >>> thing.method.assert_called_with(3, 4, 5, key='value') + >>> from unittest.mock import MagicMock + >>> thing = ProductionClass() + >>> thing.method = MagicMock(return_value=3) + >>> thing.method(3, 4, 5, key='value') + 3 + >>> thing.method.assert_called_with(3, 4, 5, key='value') :attr:`side_effect` allows you to perform side effects, including raising an exception when a mock is called: @@ -94,20 +94,20 @@ objects in a module under test. The object you specify will be replaced with a mock (or other object) during the test and restored when the test ends: .. doctest:: - :options: +SKIP - - >>> from unittest.mock import patch - >>> @patch('module.ClassName2') - ... @patch('module.ClassName1') - ... def test(MockClass1, MockClass2): - ... module.ClassName1() - ... module.ClassName2() - ... assert MockClass1 is module.ClassName1 - ... assert MockClass2 is module.ClassName2 - ... assert MockClass1.called - ... assert MockClass2.called - ... - >>> test() + :options: +SKIP + + >>> from unittest.mock import patch + >>> @patch('module.ClassName2') + ... @patch('module.ClassName1') + ... def test(MockClass1, MockClass2): + ... module.ClassName1() + ... module.ClassName2() + ... assert MockClass1 is module.ClassName1 + ... assert MockClass2 is module.ClassName2 + ... assert MockClass1.called + ... assert MockClass2.called + ... + >>> test() .. note:: @@ -124,13 +124,13 @@ As well as a decorator :func:`patch` can be used as a context manager in a with statement: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method: - ... thing = ProductionClass() - ... thing.method(1, 2, 3) - ... - >>> mock_method.assert_called_once_with(1, 2, 3) + >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method: + ... thing = ProductionClass() + ... thing.method(1, 2, 3) + ... + >>> mock_method.assert_called_once_with(1, 2, 3) There is also :func:`patch.dict` for setting values in a dictionary just @@ -521,8 +521,8 @@ the *new_callable* argument to :func:`patch`. The default return value is a mock object and you can configure it in the normal way: - >>> mock = Mock() >>> from unittest.mock import sentinel + >>> mock = Mock() >>> mock.return_value.attribute = sentinel.Attribute >>> mock.return_value() @@ -730,14 +730,14 @@ Mock objects that use a class or an instance as a :attr:`spec` or :attr:`spec_set` are able to pass :func:`isinstance` tests: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> mock = Mock(spec=SomeClass) - >>> isinstance(mock, SomeClass) - True - >>> mock = Mock(spec_set=SomeClass()) - >>> isinstance(mock, SomeClass) - True + >>> mock = Mock(spec=SomeClass) + >>> isinstance(mock, SomeClass) + True + >>> mock = Mock(spec_set=SomeClass()) + >>> isinstance(mock, SomeClass) + True The :class:`Mock` classes have support for mocking magic methods. See :ref:`magic methods ` for the full details. @@ -800,26 +800,25 @@ apply to method calls on the mock object. no args. Setting it calls the mock with the value being set. .. doctest:: - :options: +SKIP - - >>> from unittest.mock import PropertyMock - >>> class Foo: - ... @property - ... def foo(self): - ... return 'something' - ... @foo.setter - ... def foo(self, value): - ... pass - ... - >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo: - ... mock_foo.return_value = 'mockity-mock' - ... this_foo = Foo() - ... print(this_foo.foo) - ... this_foo.foo = 6 - ... - mockity-mock - >>> mock_foo.mock_calls - [call(), call(6)] + :options: +SKIP + + >>> class Foo: + ... @property + ... def foo(self): + ... return 'something' + ... @foo.setter + ... def foo(self, value): + ... pass + ... + >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo: + ... mock_foo.return_value = 'mockity-mock' + ... this_foo = Foo() + ... print(this_foo.foo) + ... this_foo.foo = 6 + ... + mockity-mock + >>> mock_foo.mock_calls + [call(), call(6)] Because of the way mock attributes are stored you can't directly attach a :class:`PropertyMock` to a mock object. Instead you can attach it to the mock type @@ -1031,20 +1030,20 @@ attach mocks that have names to a parent you use the :meth:`~Mock.attach_mock` method: .. doctest:: - :options: +SKIP - - >>> thing1 = object() - >>> thing2 = object() - >>> parent = MagicMock() - >>> with patch('__main__.thing1', return_value=None) as child1: - ... with patch('__main__.thing2', return_value=None) as child2: - ... parent.attach_mock(child1, 'child1') - ... parent.attach_mock(child2, 'child2') - ... child1('one') - ... child2('two') - ... - >>> parent.mock_calls - [call.child1('one'), call.child2('two')] + :options: +SKIP + + >>> thing1 = object() + >>> thing2 = object() + >>> parent = MagicMock() + >>> with patch('__main__.thing1', return_value=None) as child1: + ... with patch('__main__.thing2', return_value=None) as child2: + ... parent.attach_mock(child1, 'child1') + ... parent.attach_mock(child2, 'child2') + ... child1('one') + ... child2('two') + ... + >>> parent.mock_calls + [call.child1('one'), call.child2('two')] .. [#] The only exceptions are magic methods and attributes (those that have @@ -1150,14 +1149,14 @@ patch the decorated function: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> @patch('__main__.SomeClass') - ... def function(normal_argument, mock_class): - ... print(mock_class is SomeClass) - ... - >>> function(None) - True + >>> @patch('__main__.SomeClass') + ... def function(normal_argument, mock_class): + ... print(mock_class is SomeClass) + ... + >>> function(None) + True Patching a class replaces the class with a :class:`MagicMock` *instance*. If the class is instantiated in the code under test then it will be the @@ -1171,48 +1170,47 @@ To configure return values on methods of *instances* on the patched class you must do this on the :attr:`return_value`. For example: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class Class: - ... def method(self): - ... pass - ... - >>> with patch('__main__.Class') as MockClass: - ... instance = MockClass.return_value - ... instance.method.return_value = 'foo' - ... assert Class() is instance - ... assert Class().method() == 'foo' - ... + >>> class Class: + ... def method(self): + ... pass + ... + >>> with patch('__main__.Class') as MockClass: + ... instance = MockClass.return_value + ... instance.method.return_value = 'foo' + ... assert Class() is instance + ... assert Class().method() == 'foo' + ... If you use *spec* or *spec_set* and :func:`patch` is replacing a *class*, then the return value of the created mock will have the same spec. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> Original = Class - >>> patcher = patch('__main__.Class', spec=True) - >>> MockClass = patcher.start() - >>> instance = MockClass() - >>> assert isinstance(instance, Original) - >>> patcher.stop() + >>> Original = Class + >>> patcher = patch('__main__.Class', spec=True) + >>> MockClass = patcher.start() + >>> instance = MockClass() + >>> assert isinstance(instance, Original) + >>> patcher.stop() The *new_callable* argument is useful where you want to use an alternative class to the default :class:`MagicMock` for the created mock. For example, if you wanted a :class:`NonCallableMock` to be used: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> from unittest.mock import NonCallableMock - >>> thing = object() - >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing: - ... assert thing is mock_thing - ... thing() - ... - Traceback (most recent call last): - ... - TypeError: 'NonCallableMock' object is not callable + >>> thing = object() + >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing: + ... assert thing is mock_thing + ... thing() + ... + Traceback (most recent call last): + ... + TypeError: 'NonCallableMock' object is not callable Another use case might be to replace an object with an :class:`io.StringIO` instance: @@ -1233,14 +1231,14 @@ in the call to patch. Any arbitrary keywords you pass into the call will be used to set attributes on the created mock: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> patcher = patch('__main__.thing', first='one', second='two') - >>> mock_thing = patcher.start() - >>> mock_thing.first - 'one' - >>> mock_thing.second - 'two' + >>> patcher = patch('__main__.thing', first='one', second='two') + >>> mock_thing = patcher.start() + >>> mock_thing.first + 'one' + >>> mock_thing.second + 'two' As well as attributes on the created mock attributes, like the :attr:`~Mock.return_value` and :attr:`~Mock.side_effect`, of child mocks can @@ -1249,17 +1247,17 @@ keyword arguments, but a dictionary with these as keys can still be expanded into a :func:`patch` call using ``**``: .. doctest:: - :options: +SKIP - - >>> config = {'method.return_value': 3, 'other.side_effect': KeyError} - >>> patcher = patch('__main__.thing', **config) - >>> mock_thing = patcher.start() - >>> mock_thing.method() - 3 - >>> mock_thing.other() - Traceback (most recent call last): - ... - KeyError + :options: +SKIP + + >>> config = {'method.return_value': 3, 'other.side_effect': KeyError} + >>> patcher = patch('__main__.thing', **config) + >>> mock_thing = patcher.start() + >>> mock_thing.method() + 3 + >>> mock_thing.other() + Traceback (most recent call last): + ... + KeyError patch.object @@ -1288,14 +1286,14 @@ mock is created for you and passed in as an extra argument to the decorated function: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> @patch.object(SomeClass, 'class_method') - ... def test(mock_method): - ... SomeClass.class_method(3) - ... mock_method.assert_called_with(3) - ... - >>> test() + >>> @patch.object(SomeClass, 'class_method') + ... def test(mock_method): + ... SomeClass.class_method(3) + ... mock_method.assert_called_with(3) + ... + >>> test() *spec*, *create* and the other arguments to :func:`patch.object` have the same meaning as they do for :func:`patch`. @@ -1414,44 +1412,44 @@ If you want :func:`patch.multiple` to create mocks for you, then you can use then the created mocks are passed into the decorated function by keyword. .. doctest:: - :options: +SKIP - - >>> thing = object() - >>> other = object() - >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) - ... def test_function(thing, other): - ... assert isinstance(thing, MagicMock) - ... assert isinstance(other, MagicMock) - ... - >>> test_function() + :options: +SKIP + + >>> thing = object() + >>> other = object() + >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) + ... def test_function(thing, other): + ... assert isinstance(thing, MagicMock) + ... assert isinstance(other, MagicMock) + ... + >>> test_function() :func:`patch.multiple` can be nested with other ``patch`` decorators, but put arguments passed by keyword *after* any of the standard arguments created by :func:`patch`: .. doctest:: - :options: +SKIP - - >>> @patch('sys.exit') - ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) - ... def test_function(mock_exit, other, thing): - ... assert 'other' in repr(other) - ... assert 'thing' in repr(thing) - ... assert 'exit' in repr(mock_exit) - ... - >>> test_function() + :options: +SKIP + + >>> @patch('sys.exit') + ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) + ... def test_function(mock_exit, other, thing): + ... assert 'other' in repr(other) + ... assert 'thing' in repr(thing) + ... assert 'exit' in repr(mock_exit) + ... + >>> test_function() If :func:`patch.multiple` is used as a context manager, the value returned by the context manger is a dictionary where created mocks are keyed by name: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values: - ... assert 'other' in repr(values['other']) - ... assert 'thing' in repr(values['thing']) - ... assert values['thing'] is thing - ... assert values['other'] is other - ... + >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values: + ... assert 'other' in repr(values['other']) + ... assert 'thing' in repr(values['thing']) + ... assert values['thing'] is thing + ... assert values['other'] is other + ... .. _start-and-stop: @@ -1471,17 +1469,17 @@ If you are using :func:`patch` to create a mock for you then it will be returned the call to ``patcher.start``. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> patcher = patch('package.module.ClassName') - >>> from package import module - >>> original = module.ClassName - >>> new_mock = patcher.start() - >>> assert module.ClassName is not original - >>> assert module.ClassName is new_mock - >>> patcher.stop() - >>> assert module.ClassName is original - >>> assert module.ClassName is not new_mock + >>> patcher = patch('package.module.ClassName') + >>> from package import module + >>> original = module.ClassName + >>> new_mock = patcher.start() + >>> assert module.ClassName is not original + >>> assert module.ClassName is new_mock + >>> patcher.stop() + >>> assert module.ClassName is original + >>> assert module.ClassName is not new_mock A typical use case for this might be for doing multiple patches in the ``setUp`` @@ -1540,15 +1538,15 @@ You can patch any builtins within a module. The following example patches builtin :func:`ord`: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> @patch('__main__.ord') - ... def test(mock_ord): - ... mock_ord.return_value = 101 - ... print(ord('c')) - ... - >>> test() - 101 + >>> @patch('__main__.ord') + ... def test(mock_ord): + ... mock_ord.return_value = 101 + ... print(ord('c')) + ... + >>> test() + 101 TEST_PREFIX @@ -1563,25 +1561,25 @@ It is possible that you want to use a different prefix for your tests. You can inform the patchers of the different prefix by setting ``patch.TEST_PREFIX``: .. doctest:: - :options: +SKIP - - >>> patch.TEST_PREFIX = 'foo' - >>> value = 3 - >>> - >>> @patch('__main__.value', 'not three') - ... class Thing: - ... def foo_one(self): - ... print(value) - ... def foo_two(self): - ... print(value) - ... - >>> - >>> Thing().foo_one() - not three - >>> Thing().foo_two() - not three - >>> value - 3 + :options: +SKIP + + >>> patch.TEST_PREFIX = 'foo' + >>> value = 3 + >>> + >>> @patch('__main__.value', 'not three') + ... class Thing: + ... def foo_one(self): + ... print(value) + ... def foo_two(self): + ... print(value) + ... + >>> + >>> Thing().foo_one() + not three + >>> Thing().foo_two() + not three + >>> value + 3 Nesting Patch Decorators @@ -1593,20 +1591,20 @@ decorators. You can stack up multiple patch decorators using this pattern: .. doctest:: - :options: +SKIP - - >>> @patch.object(SomeClass, 'class_method') - ... @patch.object(SomeClass, 'static_method') - ... def test(mock1, mock2): - ... assert SomeClass.static_method is mock1 - ... assert SomeClass.class_method is mock2 - ... SomeClass.static_method('foo') - ... SomeClass.class_method('bar') - ... return mock1, mock2 - ... - >>> mock1, mock2 = test() - >>> mock1.assert_called_once_with('foo') - >>> mock2.assert_called_once_with('bar') + :options: +SKIP + + >>> @patch.object(SomeClass, 'class_method') + ... @patch.object(SomeClass, 'static_method') + ... def test(mock1, mock2): + ... assert SomeClass.static_method is mock1 + ... assert SomeClass.class_method is mock2 + ... SomeClass.static_method('foo') + ... SomeClass.class_method('bar') + ... return mock1, mock2 + ... + >>> mock1, mock2 = test() + >>> mock1.assert_called_once_with('foo') + >>> mock2.assert_called_once_with('bar') Note that the decorators are applied from the bottom upwards. This is the @@ -1916,15 +1914,15 @@ creating and testing the identity of objects like this. In this example we monkey patch ``method`` to return ``sentinel.some_object``: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> real = ProductionClass() - >>> real.method = Mock(name="method") - >>> real.method.return_value = sentinel.some_object - >>> result = real.method() - >>> assert result is sentinel.some_object - >>> sentinel.some_object - sentinel.some_object + >>> real = ProductionClass() + >>> real.method = Mock(name="method") + >>> real.method.return_value = sentinel.some_object + >>> result = real.method() + >>> assert result is sentinel.some_object + >>> sentinel.some_object + sentinel.some_object DEFAULT @@ -2104,22 +2102,22 @@ attributes from the original are shown, even if they haven't been accessed yet: .. doctest:: - :options: +NORMALIZE_WHITESPACE - - >>> dir(Mock()) - ['assert_any_call', - 'assert_called', - 'assert_called_once', - 'assert_called_once_with', - 'assert_called_with', - ... - >>> from urllib import request - >>> dir(Mock(spec=request)) - ['AbstractBasicAuthHandler', - 'AbstractDigestAuthHandler', - 'AbstractHTTPHandler', - 'BaseHandler', - ... + :options: +SKIP + + >>> dir(Mock()) + ['assert_any_call', + 'assert_called_once_with', + 'assert_called_with', + 'assert_has_calls', + 'attach_mock', + ... + >>> from urllib import request + >>> dir(Mock(spec=request)) + ['AbstractBasicAuthHandler', + 'AbstractDigestAuthHandler', + 'AbstractHTTPHandler', + 'BaseHandler', + ... Many of the not-very-useful (private to :class:`Mock` rather than the thing being mocked) underscore and double underscore prefixed attributes have been @@ -2128,19 +2126,19 @@ behaviour you can switch it off by setting the module level switch :data:`FILTER_DIR`: .. doctest:: - :options: +SKIP - - >>> from unittest import mock - >>> mock.FILTER_DIR = False - >>> dir(mock.Mock()) - ['_NonCallableMock__get_return_value', - '_NonCallableMock__get_side_effect', - '_NonCallableMock__return_value_doc', - '_NonCallableMock__set_return_value', - '_NonCallableMock__set_side_effect', - '__call__', - '__class__', - ... + :options: +SKIP + + >>> from unittest import mock + >>> mock.FILTER_DIR = False + >>> dir(mock.Mock()) + ['_NonCallableMock__get_return_value', + '_NonCallableMock__get_side_effect', + '_NonCallableMock__return_value_doc', + '_NonCallableMock__set_return_value', + '_NonCallableMock__set_side_effect', + '__call__', + '__class__', + ... Alternatively you can just use ``vars(my_mock)`` (instance members) and ``dir(type(my_mock))`` (type members) to bypass the filtering irrespective of @@ -2191,33 +2189,33 @@ Mocking context managers with a :class:`MagicMock` is common enough and fiddly enough that a helper function is useful. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> m = mock_open() - >>> with patch('__main__.open', m): - ... with open('foo', 'w') as h: - ... h.write('some stuff') - ... - >>> m.mock_calls - [call('foo', 'w'), - call().__enter__(), - call().write('some stuff'), - call().__exit__(None, None, None)] - >>> m.assert_called_once_with('foo', 'w') - >>> handle = m() - >>> handle.write.assert_called_once_with('some stuff') + >>> m = mock_open() + >>> with patch('__main__.open', m): + ... with open('foo', 'w') as h: + ... h.write('some stuff') + ... + >>> m.mock_calls + [call('foo', 'w'), + call().__enter__(), + call().write('some stuff'), + call().__exit__(None, None, None)] + >>> m.assert_called_once_with('foo', 'w') + >>> handle = m() + >>> handle.write.assert_called_once_with('some stuff') And for reading files: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> with patch('__main__.open', mock_open(read_data='bibble')) as m: - ... with open('foo') as h: - ... result = h.read() - ... - >>> m.assert_called_once_with('foo') - >>> assert result == 'bibble' + >>> with patch('__main__.open', mock_open(read_data='bibble')) as m: + ... with open('foo') as h: + ... result = h.read() + ... + >>> m.assert_called_once_with('foo') + >>> assert result == 'bibble' .. _auto-speccing: @@ -2306,15 +2304,15 @@ hit. Here's an example of it in use: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> from urllib import request - >>> patcher = patch('__main__.request', autospec=True) - >>> mock_request = patcher.start() - >>> request is mock_request - True - >>> mock_request.Request - + >>> from urllib import request + >>> patcher = patch('__main__.request', autospec=True) + >>> mock_request = patcher.start() + >>> request is mock_request + True + >>> mock_request.Request + You can see that :class:`request.Request` has a spec. :class:`request.Request` takes two arguments in the constructor (one of which is *self*). Here's what happens if @@ -2329,26 +2327,26 @@ The spec also applies to instantiated classes (i.e. the return value of specced mocks): .. doctest:: - :options: +SKIP + :options: +SKIP - >>> req = request.Request('foo') - >>> req - + >>> req = request.Request('foo') + >>> req + :class:`Request` objects are not callable, so the return value of instantiating our mocked out :class:`request.Request` is a non-callable mock. With the spec in place any typos in our asserts will raise the correct error: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> req.add_header('spam', 'eggs') - - >>> req.add_header.assret_called_with - Traceback (most recent call last): - ... - AttributeError: Mock object has no attribute 'assret_called_with' - >>> req.add_header.assert_called_with('spam', 'eggs') + >>> req.add_header('spam', 'eggs') + + >>> req.add_header.assret_called_with + Traceback (most recent call last): + ... + AttributeError: Mock object has no attribute 'assret_called_with' + >>> req.add_header.assert_called_with('spam', 'eggs') In many cases you will just be able to add ``autospec=True`` to your existing :func:`patch` calls and then be protected against bugs due to typos and api @@ -2377,19 +2375,19 @@ created in the :meth:`__init__` method and not to exist on the class at all. the api to visible attributes. .. doctest:: - :options: +SKIP + :options: +SKIP - >>> class Something: - ... def __init__(self): - ... self.a = 33 - ... - >>> with patch('__main__.Something', autospec=True): - ... thing = Something() - ... thing.a - ... - Traceback (most recent call last): - ... - AttributeError: Mock object has no attribute 'a' + >>> class Something: + ... def __init__(self): + ... self.a = 33 + ... + >>> with patch('__main__.Something', autospec=True): + ... thing = Something() + ... thing.a + ... + Traceback (most recent call last): + ... + AttributeError: Mock object has no attribute 'a' There are a few different ways of resolving this problem. The easiest, but not necessarily the least annoying, way is to simply set the required @@ -2398,12 +2396,12 @@ you to fetch attributes that don't exist on the spec it doesn't prevent you setting them: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> with patch('__main__.Something', autospec=True): - ... thing = Something() - ... thing.a = 33 - ... + >>> with patch('__main__.Something', autospec=True): + ... thing = Something() + ... thing.a = 33 + ... There is a more aggressive version of both *spec* and *autospec* that *does* prevent you setting non-existent attributes. This is useful if you want to @@ -2411,15 +2409,15 @@ ensure your code only *sets* valid attributes too, but obviously it prevents this particular scenario: .. doctest:: - :options: +SKIP + :options: +SKIP - >>> with patch('__main__.Something', autospec=True, spec_set=True): - ... thing = Something() - ... thing.a = 33 - ... - Traceback (most recent call last): + >>> with patch('__main__.Something', autospec=True, spec_set=True): + ... thing = Something() + ... thing.a = 33 ... - AttributeError: Mock object has no attribute 'a' + Traceback (most recent call last): + ... + AttributeError: Mock object has no attribute 'a' Probably the best way of solving the problem is to add class attributes as default values for instance members initialised in :meth:`__init__`. Note that if @@ -2455,20 +2453,19 @@ the spec. Thankfully :func:`patch` supports this - you can simply pass the alternative object as the *autospec* argument: .. doctest:: - :options: +SKIP + :options: +SKIP - - >>> class Something: - ... def __init__(self): - ... self.a = 33 - ... - >>> class SomethingForTest(Something): - ... a = 33 - ... - >>> p = patch('__main__.Something', autospec=SomethingForTest) - >>> mock = p.start() - >>> mock.a - + >>> class Something: + ... def __init__(self): + ... self.a = 33 + ... + >>> class SomethingForTest(Something): + ... a = 33 + ... + >>> p = patch('__main__.Something', autospec=SomethingForTest) + >>> mock = p.start() + >>> mock.a + .. [#] This only applies to classes or already instantiated objects. Calling