Author sfreilich
Recipients sfreilich
Date 2019-03-19.15:57:41
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1553011061.53.0.157389839215.issue36366@roundup.psfhosted.org>
In-reply-to
Content
Currently, it's an error to call the stop() method of a patcher object created by mock.patch repeatedly:

>>> patch = mock.patch.object(Foo, 'BAR', 'x')
>>> patch.start()
'x'
>>> patch.stop()
>>> patch.stop()
RuntimeError: stop called on unstarted patcher

This causes unnecessary problems when test classes using mock.patch.stopall for cleanup are mixed with those cleaning up patches individually:

class TestA(unittest.TestCase):

  def setUp():
    patcher = mock.patch.object(...)
    self.mock_a = patcher.start()
    self.addCleanup(patcher.stop)

  ...


class TestB(TestA):

  def setUp():
    super().setUp()
    self.addCleanup(mock.patch.stopall)
    self.mock_b = mock.patch.object(...).start()

  ...


This fails because mock.patch.stopall stops the patch set up in TestA.setUp(), then that raises an exception when it's stopped again.

But why does patcher.stop() enforce that precondition? Wouldn't it be sufficient for it to just enforce the postcondition, that after stop() is called the patch is stopped()? That would make it easier to write test code which makes use of mock.patch.stopall, which allows the proper cleanup of patches to be configured much more concisely.
History
Date User Action Args
2019-03-19 15:57:41sfreilichsetrecipients: + sfreilich
2019-03-19 15:57:41sfreilichsetmessageid: <1553011061.53.0.157389839215.issue36366@roundup.psfhosted.org>
2019-03-19 15:57:41sfreilichlinkissue36366 messages
2019-03-19 15:57:41sfreilichcreate