为 `mock.patch` 做一个包装器
Making a wrapper for `mock.patch`
来自 mock.patch
的一些自定义补丁我想一遍又一遍地使用补丁设置的复制粘贴而不乱扔我的测试代码。例如this very handy patch of datetime.date
,适用于日期时间,将用
填充我的代码
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)
如何将此功能封装到单行调用中?
这里有一个资源管理器 class 可以为您做这件事。由于您可能希望将它放在与测试 classes 不同的文件中,因此它使用 inspect
查找调用模块,以便它可以将正确限定的目标模块名称传递给 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()
然后您可以使用
调用它
with mock_datetime('mymodule.datetime', datetime.datetime(2016, 3, 23)):
assert mymodule.datetime.datetime.utcnow() == datetime.datetime(2016, 3, 23)
@brandones 的解决方案非常棒!但是我发现如果你省去检查会更容易使用,就像这样:
# 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)
来自 mock.patch
的一些自定义补丁我想一遍又一遍地使用补丁设置的复制粘贴而不乱扔我的测试代码。例如this very handy patch of datetime.date
,适用于日期时间,将用
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)
如何将此功能封装到单行调用中?
这里有一个资源管理器 class 可以为您做这件事。由于您可能希望将它放在与测试 classes 不同的文件中,因此它使用 inspect
查找调用模块,以便它可以将正确限定的目标模块名称传递给 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()
然后您可以使用
调用它with mock_datetime('mymodule.datetime', datetime.datetime(2016, 3, 23)):
assert mymodule.datetime.datetime.utcnow() == datetime.datetime(2016, 3, 23)
@brandones 的解决方案非常棒!但是我发现如果你省去检查会更容易使用,就像这样:
# 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)