diff -r fe532dccf8f6 Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst Mon Apr 14 10:30:43 2014 -0400 +++ b/Doc/library/unittest.mock.rst Mon Apr 14 22:36:47 2014 +0530 @@ -1031,6 +1031,11 @@ default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! + .. note:: + + If you are patching any builtins inside 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 +1406,21 @@ 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 ~~~~~~~~~~~ diff -r fe532dccf8f6 Lib/unittest/mock.py --- a/Lib/unittest/mock.py Mon Apr 14 10:30:43 2014 -0400 +++ b/Lib/unittest/mock.py Mon Apr 14 22:36:47 2014 +0530 @@ -27,9 +27,13 @@ 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 @@ -1155,6 +1159,9 @@ 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 -r fe532dccf8f6 Lib/unittest/test/testmock/testpatch.py --- a/Lib/unittest/test/testmock/testpatch.py Mon Apr 14 10:30:43 2014 -0400 +++ b/Lib/unittest/test/testmock/testpatch.py Mon Apr 14 22:36:47 2014 +0530 @@ -377,7 +377,7 @@ 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 @@ 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):