Making a wrapper for `mock.patch`

ⅰ亾dé卋堺 提交于 2019-12-11 05:42:31

问题


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, which, adapted for datetime, would fill my code with

with patch('mymodule.datetime') as mock_datetime:
    mock_datetime.datetime.utcnow.return_value = datetime.datetime(2010, 10, 8, 9, 10)
    mock_date.datetime.side_effect = lambda *args, **kw: datetime.datetime(*args, **kw)

How can I wrap this functionality into a one-line call?


回答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 version

class mock_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

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



回答2:


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

# testhelpers.py
import unittest.mock as mock
import datetime

class MockDatetime():
    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.py
import datetime
from testhelpers import MockDatetime

def test__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)


来源:https://stackoverflow.com/questions/40334806/making-a-wrapper-for-mock-patch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!