summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Corchero <mariocj89@gmail.com>2020-01-24 08:38:33 (GMT)
committerChris Withers <chris@withers.org>2020-01-24 08:38:32 (GMT)
commite131c9720d087c0c4988bd2a5c62020feb9d1d77 (patch)
tree209230859dbb25990ed04ce139bf06abac490e04
parent1d0c5e16eab29d55773cc4196bb90d2bf12e09dd (diff)
downloadcpython-e131c9720d087c0c4988bd2a5c62020feb9d1d77.zip
cpython-e131c9720d087c0c4988bd2a5c62020feb9d1d77.tar.gz
cpython-e131c9720d087c0c4988bd2a5c62020feb9d1d77.tar.bz2
Fix `mock.patch.dict` to be stopped with `mock.patch.stopall` (#17606)
As the function was not registering in the active patches, the mocks started by `mock.patch.dict` were not being stopped when `mock.patch.stopall` was being called.
-rw-r--r--Lib/unittest/mock.py19
-rw-r--r--Lib/unittest/test/testmock/testpatch.py50
-rw-r--r--Misc/NEWS.d/next/Library/2019-12-14-14-38-40.bpo-21600.kC4Cgh.rst2
3 files changed, 69 insertions, 2 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 5622917..3fafe59 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -1851,8 +1851,23 @@ class _patch_dict(object):
self._unpatch_dict()
return False
- start = __enter__
- stop = __exit__
+
+ def start(self):
+ """Activate a patch, returning any created mock."""
+ result = self.__enter__()
+ _patch._active_patches.append(self)
+ return result
+
+
+ def stop(self):
+ """Stop an active patch."""
+ try:
+ _patch._active_patches.remove(self)
+ except ValueError:
+ # If the patch hasn't been started this will fail
+ pass
+
+ return self.__exit__()
def _clear_dict(in_dict):
diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py
index dc4ccdb..438dfd8 100644
--- a/Lib/unittest/test/testmock/testpatch.py
+++ b/Lib/unittest/test/testmock/testpatch.py
@@ -1808,6 +1808,56 @@ class PatchTest(unittest.TestCase):
self.assertEqual(stopped, ["three", "two", "one"])
+ def test_patch_dict_stopall(self):
+ dic1 = {}
+ dic2 = {1: 'a'}
+ dic3 = {1: 'A', 2: 'B'}
+ origdic1 = dic1.copy()
+ origdic2 = dic2.copy()
+ origdic3 = dic3.copy()
+ patch.dict(dic1, {1: 'I', 2: 'II'}).start()
+ patch.dict(dic2, {2: 'b'}).start()
+
+ @patch.dict(dic3)
+ def patched():
+ del dic3[1]
+
+ patched()
+ self.assertNotEqual(dic1, origdic1)
+ self.assertNotEqual(dic2, origdic2)
+ self.assertEqual(dic3, origdic3)
+
+ patch.stopall()
+
+ self.assertEqual(dic1, origdic1)
+ self.assertEqual(dic2, origdic2)
+ self.assertEqual(dic3, origdic3)
+
+
+ def test_patch_and_patch_dict_stopall(self):
+ original_unlink = os.unlink
+ original_chdir = os.chdir
+ dic1 = {}
+ dic2 = {1: 'A', 2: 'B'}
+ origdic1 = dic1.copy()
+ origdic2 = dic2.copy()
+
+ patch('os.unlink', something).start()
+ patch('os.chdir', something_else).start()
+ patch.dict(dic1, {1: 'I', 2: 'II'}).start()
+ patch.dict(dic2).start()
+ del dic2[1]
+
+ self.assertIsNot(os.unlink, original_unlink)
+ self.assertIsNot(os.chdir, original_chdir)
+ self.assertNotEqual(dic1, origdic1)
+ self.assertNotEqual(dic2, origdic2)
+ patch.stopall()
+ self.assertIs(os.unlink, original_unlink)
+ self.assertIs(os.chdir, original_chdir)
+ self.assertEqual(dic1, origdic1)
+ self.assertEqual(dic2, origdic2)
+
def test_special_attrs(self):
def foo(x=0):
diff --git a/Misc/NEWS.d/next/Library/2019-12-14-14-38-40.bpo-21600.kC4Cgh.rst b/Misc/NEWS.d/next/Library/2019-12-14-14-38-40.bpo-21600.kC4Cgh.rst
new file mode 100644
index 0000000..0f72639
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-12-14-14-38-40.bpo-21600.kC4Cgh.rst
@@ -0,0 +1,2 @@
+Fix :func:`mock.patch.stopall` to stop active patches that were created with
+:func:`mock.patch.dict`.