def __exit__(self, *exc_info):
"""Undo the patch."""
if not _is_started(self):
- raise RuntimeError('stop called on unstarted patcher')
+ return
if self.is_local and self.temp_original is not DEFAULT:
setattr(self.target, self.attribute, self.temp_original)
def test_stop_without_start(self):
+ # bpo-36366: calling stop without start will return None.
patcher = patch(foo_name, 'bar', 3)
+ self.assertIsNone(patcher.stop())
- # calling stop without start used to produce a very obscure error
- self.assertRaises(RuntimeError, patcher.stop)
+
+ def test_stop_idempotent(self):
+ # bpo-36366: calling stop on an already stopped patch will return None.
+ patcher = patch(foo_name, 'bar', 3)
+
+ patcher.start()
+ patcher.stop()
+ self.assertIsNone(patcher.stop())
def test_patchobject_start_stop(self):
--- /dev/null
+Calling ``stop()`` on an unstarted or stopped :func:`unittest.mock.patch`
+object will now return `None` instead of raising :exc:`RuntimeError`,
+making the method idempotent.
+Patch byKarthikeyan Singaravelan.