Skip to content Skip to sidebar Skip to footer

Making A Wrapper For `mock.patch`

Some customized patches from mock.patch I want to use over and over without littering my test code with copy-pastes of the patch setup. e.g. this very handy patch of datetime.date,

Solution 1:

Here's a resource manager class that will do that for you. Since you might want to put it in a separate file from your test classes, it uses inspect to look up the calling module, so that it can pass the correctly qualified target module name to mock.patch.

import datetime
import inspect
# import mock according to your python versionclassmock_datetime(object):

    def__init__(self, target, new_utcnow):
        self.new_utcnow = new_utcnow
        self.target = target

    def__enter__(self):
        calling_module = inspect.getmodule(inspect.stack()[1][0])
        target_from_here = calling_module.__name__ + '.' + self.target
        self.patcher = mock.patch(target_from_here)
        mock_dt = self.patcher.start()
        mock_dt.datetime.utcnow.return_value = self.new_utcnow.replace(tzinfo=None)
        mock_dt.datetime.side_effect = lambda *args, **kw: datetime.datetime(*args, **kw)
        return mock_dt

    def__exit__(self, *args, **kwargs):
        self.patcher.stop()

You can then invoke it with

withmock_datetime('mymodule.datetime', datetime.datetime(2016, 3, 23)):
    assert mymodule.datetime.datetime.utcnow() == datetime.datetime(2016, 3, 23)

Solution 2:

The solution by @brandones is excellent! But I found it easier to use if you leave out the inspection, like this:

# testhelpers.pyimport unittest.mock as mock
import datetime

classMockDatetime():
    def__init__(self, target, utcnow):
        self.utcnow = utcnow
        self.target = target

    def__enter__(self):
        self.patcher = mock.patch(self.target)
        mock_dt = self.patcher.start()
        mock_dt.datetime.utcnow.return_value = self.utcnow.replace(tzinfo=None)
        mock_dt.datetime.side_effect = lambda *args, **kw: datetime.datetime(*args, **kw)
        return mock_dt

    def__exit__(self, *args, **kwargs):
        self.patcher.stop()


# testhelpers_test.pyimport datetime
from testhelpers import MockDatetime

deftest__mock_datetime():
    with MockDatetime('testhelpers_test.datetime', datetime.datetime(2019, 4, 29, 9, 10, 23, 1234)):
        assert datetime.datetime.utcnow() == datetime.datetime(2019, 4, 29, 9, 10, 23, 1234)

Post a Comment for "Making A Wrapper For `mock.patch`"