summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Foord <michael@voidspace.org.uk>2014-04-14 20:25:20 (GMT)
committerMichael Foord <michael@voidspace.org.uk>2014-04-14 20:25:20 (GMT)
commitfddcfa27fab71ceb6a9df3f4edf46e94ee1da94f (patch)
treee2023b0ee586885b354d62492d14b95f5b3a57cb
parentfba913f77aa53dff416753c987bf590762c98406 (diff)
downloadcpython-fddcfa27fab71ceb6a9df3f4edf46e94ee1da94f.zip
cpython-fddcfa27fab71ceb6a9df3f4edf46e94ee1da94f.tar.gz
cpython-fddcfa27fab71ceb6a9df3f4edf46e94ee1da94f.tar.bz2
Closes issue 17660. You no longer need to explicitly pass create=True when patching builtin names.
-rw-r--r--Doc/library/unittest.mock.rst25
-rw-r--r--Lib/unittest/mock.py7
-rw-r--r--Lib/unittest/test/testmock/testpatch.py24
3 files changed, 52 insertions, 4 deletions
diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst
index cb72a68..6d4b82b 100644
--- a/Doc/library/unittest.mock.rst
+++ b/Doc/library/unittest.mock.rst
@@ -1031,6 +1031,12 @@ patch
default because it can be dangerous. With it switched on you can write
passing tests against APIs that don't actually exist!
+ .. note::
+
+ .. versionchanged:: 3.5
+ If you are patching builtins in a module then you don't
+ need to pass `create=True`, it will be added by default.
+
Patch can be used as a `TestCase` class decorator. It works by
decorating each test method in the class. This reduces the boilerplate
code when your test methods share a common patchings set. `patch` finds
@@ -1401,6 +1407,21 @@ It is also possible to stop all patches which have been started by using
Stop all active patches. Only stops patches started with `start`.
+.. patch-builtins:
+
+patch builtins
+~~~~~~~~~~~~~~~
+You can patch any builtins within a module. The following example patches
+builtin `ord`:
+
+ >>> @patch('__main__.ord')
+ ... def test(mock_ord):
+ ... mock_ord.return_value = 101
+ ... print(ord('c'))
+ ...
+ >>> test()
+ 101
+
TEST_PREFIX
~~~~~~~~~~~
@@ -2011,7 +2032,7 @@ Mocking context managers with a :class:`MagicMock` is common enough and fiddly
enough that a helper function is useful.
>>> m = mock_open()
- >>> with patch('__main__.open', m, create=True):
+ >>> with patch('__main__.open', m):
... with open('foo', 'w') as h:
... h.write('some stuff')
...
@@ -2026,7 +2047,7 @@ enough that a helper function is useful.
And for reading files:
- >>> with patch('__main__.open', mock_open(read_data='bibble'), create=True) as m:
+ >>> with patch('__main__.open', mock_open(read_data='bibble')) as m:
... with open('foo') as h:
... result = h.read()
...
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index f1f6522..2dd4ca5 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -27,9 +27,13 @@ __version__ = '1.0'
import inspect
import pprint
import sys
+import builtins
+from types import ModuleType
from functools import wraps, partial
+_builtins = {name for name in dir(builtins) if not name.startswith('_')}
+
BaseExceptions = (BaseException,)
if 'java' in sys.platform:
# jython
@@ -1166,6 +1170,9 @@ class _patch(object):
else:
local = True
+ if name in _builtins and isinstance(target, ModuleType):
+ self.create = True
+
if not self.create and original is DEFAULT:
raise AttributeError(
"%s does not have the attribute %r" % (target, name)
diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py
index c1bc34f..d941d8a 100644
--- a/Lib/unittest/test/testmock/testpatch.py
+++ b/Lib/unittest/test/testmock/testpatch.py
@@ -377,7 +377,7 @@ class PatchTest(unittest.TestCase):
def test_patchobject_wont_create_by_default(self):
try:
- @patch.object(SomeClass, 'frooble', sentinel.Frooble)
+ @patch.object(SomeClass, 'ord', sentinel.Frooble)
def test():
self.fail('Patching non existent attributes should fail')
@@ -386,7 +386,27 @@ class PatchTest(unittest.TestCase):
pass
else:
self.fail('Patching non existent attributes should fail')
- self.assertFalse(hasattr(SomeClass, 'frooble'))
+ self.assertFalse(hasattr(SomeClass, 'ord'))
+
+
+ def test_patch_builtins_without_create(self):
+ @patch(__name__+'.ord')
+ def test_ord(mock_ord):
+ mock_ord.return_value = 101
+ return ord('c')
+
+ @patch(__name__+'.open')
+ def test_open(mock_open):
+ m = mock_open.return_value
+ m.read.return_value = 'abcd'
+
+ fobj = open('doesnotexists.txt')
+ data = fobj.read()
+ fobj.close()
+ return data
+
+ self.assertEqual(test_ord(), 101)
+ self.assertEqual(test_open(), 'abcd')
def test_patch_with_static_methods(self):