谁能告诉我为什么这行不通?
>>> import mock
>>> @mock.patch('datetime.date.today')
... def today(cls):
... return date(2010, 1, 1)
...
>>> from datetime import date
>>> date.today()
datetime.date(2010, 12, 19)
也许有人能提出一个更好的办法?
谁能告诉我为什么这行不通?
>>> import mock
>>> @mock.patch('datetime.date.today')
... def today(cls):
... return date(2010, 1, 1)
...
>>> from datetime import date
>>> date.today()
datetime.date(2010, 12, 19)
也许有人能提出一个更好的办法?
当前回答
可以在不添加side_effects的情况下模拟datetime模块中的函数
import mock
from datetime import datetime
from where_datetime_used import do
initial_date = datetime.strptime('2018-09-27', "%Y-%m-%d")
with mock.patch('where_datetime_used.datetime') as mocked_dt:
mocked_dt.now.return_value = initial_date
do()
其他回答
在Daniel G的解决方案中补充一点:
from datetime import date
class FakeDate(date):
"A manipulable date replacement"
def __new__(cls, *args, **kwargs):
return date.__new__(date, *args, **kwargs)
这将创建一个类,当实例化时,该类将返回一个正常的datetime。对象,但也可以更改。
@mock.patch('datetime.date', FakeDate)
def test():
from datetime import date
FakeDate.today = classmethod(lambda cls: date(2010, 1, 1))
return date.today()
test() # datetime.date(2010, 1, 1)
我使用自定义装饰器实现了@user3016183方法:
def changeNow(func, newNow = datetime(2015, 11, 23, 12, 00, 00)):
"""decorator used to change datetime.datetime.now() in the tested function."""
def retfunc(self):
with mock.patch('mymodule.datetime') as mock_date:
mock_date.now.return_value = newNow
mock_date.side_effect = lambda *args, **kw: datetime(*args, **kw)
func(self)
return retfunc
我想这也许有一天能帮到别人…
我们可以使用pytest-mock (https://pypi.org/project/pytest-mock/)模拟器对象来模拟特定模块中的日期时间行为
假设您想在以下文件中模拟日期时间
# File path - source_dir/x/a.py
import datetime
def name_function():
name = datetime.now()
return f"name_{name}"
在测试函数中,mock将在测试运行时添加到函数中
def test_name_function(mocker):
mocker.patch('x.a.datetime')
x.a.datetime.now.return_value = datetime(2019, 1, 1)
actual = name_function()
assert actual == "name_2019-01-01"
也许您可以使用自己的“today()”方法,在需要的地方打补丁。使用utcnow()的示例可以在这里找到:https://bitbucket.org/k_bx/blog/src/tip/source/en_posts/2012-07-13-double-call-hack.rst?at=default
http://blog.xelnor.net/python-mocking-datetime/中讨论了几种解决方案。总而言之:
模拟对象-简单有效,但打破isinstance()检查:
target = datetime.datetime(2009, 1, 1)
with mock.patch.object(datetime, 'datetime', mock.Mock(wraps=datetime.datetime)) as patched:
patched.now.return_value = target
print(datetime.datetime.now())
模拟类
import datetime
import mock
real_datetime_class = datetime.datetime
def mock_datetime_now(target, dt):
class DatetimeSubclassMeta(type):
@classmethod
def __instancecheck__(mcs, obj):
return isinstance(obj, real_datetime_class)
class BaseMockedDatetime(real_datetime_class):
@classmethod
def now(cls, tz=None):
return target.replace(tzinfo=tz)
@classmethod
def utcnow(cls):
return target
# Python2 & Python3 compatible metaclass
MockedDatetime = DatetimeSubclassMeta('datetime', (BaseMockedDatetime,), {})
return mock.patch.object(dt, 'datetime', MockedDatetime)
使用:
with mock_datetime_now(target, datetime):
....