Toggling Python’s unit test mock patchers

I have recently found out about handy start and stop patch methods in Python’s mock library (or unittest.mock since Python 3.3). I started using it immediately and one of the first improvements I could think of was the ability to toggle the patcher off/on for a single test case using a decorator.

If you are not familiar with start and stop methods you can start out reading mock documentation (or for 3.3+). If you can’t think of a use case, it’s probably not for you. :) Otherwise, you can find both the code and the example usage below.

Code

# tests/utils/decorators.py
 
def toggle_mock_patcher(patcher):
    def wrap_f(function):
        def wrapped_f(self, *args, **kwargs):
            # check if patcher is defined and stop
            if hasattr(self, patcher):
                getattr(self, patcher).stop()
            # execute wrapped function
            function(self, *args, **kwargs)
            # check if patcher is defined and start
            if hasattr(self, patcher):
                getattr(self, patcher).start()
        return wrapped_f
    return wrap_f

Example

# tests/patcher.py
import mock
from utils.decorators import toggle_mock_patcher
 
class PatcherTestCase(unittest.TestCase):
    def setUp(self):
        super(PatcherTestCase, self).setUp()
        self.patcher1 = mock.patch('package.module.Class1')
        self.MockClass1 = self.patcher1.start()
 
    def tearDown(self):
        self.patcher1.stop()
 
    def test_patcher1_started(self):
        assert package.module.Class1 is self.MockClass1
 
    @toggle_mock_patcher('patcher1')
    def test_patcher1_stopped(self):
        assert package.module.Class1 is not self.MockClass1

Leave a Reply