如何monkeypatch python';s datetime.datetime.now是否使用py.test?
我需要测试使用如何monkeypatch python';s datetime.datetime.now是否使用py.test?,python,datetime,mocking,pytest,Python,Datetime,Mocking,Pytest,我需要测试使用datetime.datetime.now()的函数。最简单的方法是什么?您需要使用monkeypatch datetime.now函数。在下面的示例中,我正在创建夹具,稍后可以在其他测试中重复使用: import datetime import pytest FAKE_TIME = datetime.datetime(2020, 12, 25, 17, 5, 55) @pytest.fixture def patch_datetime_now(monkeypatch):
datetime.datetime.now()的函数。最简单的方法是什么?您需要使用monkeypatch datetime.now函数。在下面的示例中,我正在创建夹具,稍后可以在其他测试中重复使用:
import datetime
import pytest
FAKE_TIME = datetime.datetime(2020, 12, 25, 17, 5, 55)
@pytest.fixture
def patch_datetime_now(monkeypatch):
class mydatetime:
@classmethod
def now(cls):
return FAKE_TIME
monkeypatch.setattr(datetime, 'datetime', mydatetime)
def test_patch_datetime(patch_datetime_now):
assert datetime.datetime.now() == FAKE_TIME
这是我用来覆盖now()但保持datetime其余部分工作的装置(关于:satoru的问题)
它没有经过广泛的测试,但它确实解决了在其他上下文中使用datetime的问题。对我来说,让Django ORM使用这些日期时间值(特别是isinstance(Freeze.now(),datetime.datetime)==True
)非常重要
也许是离题了,但对于其他人来说,这可能是一个有用的问题。此夹具允许“冻结”时间,然后在测试中随意来回移动:
def test_timesensitive(freeze):
freeze.freeze(2015, 1, 1)
foo.prepare() # Uses datetime.now() to prepare its state
freeze.delta(days=2)
# Does something that takes in consideration that 2 days have passed
# i.e. datetime.now() returns a date 2 days in the future
foo.do_something()
assert foo.result == expected_result_after_2_days
有:
冻结时间()
也可以用作上下文管理器。模块支持指定本地时区UTC偏移。根据其他答案改编:
import datetime as dt
from contextlib import contextmanager
from unittest.mock import patch
@contextmanager
def mocked_now(now):
class MockedDatetime(dt.datetime):
@classmethod
def now(cls):
return now
with patch("datetime.datetime", MockedDatetime):
yield
用法如下:
def test_now():
with mocked_now(dt.datetime(2017, 10, 21)):
assert dt.datetime.now() == dt.datetime(2017, 10, 21)
使用MagicMock(wrap=datetime.datetime)怎么样
此方法模拟datetime.datetime.now()
,但其他方法与原始的datetime.datetime
方法相同
from unittest.mock import MagicMock
def test_datetime_now(monkeypatch):
import datetime
FAKE_NOW = datetime.datetime(2020, 3, 11, 14, 0, 0)
datetime_mock = MagicMock(wraps=datetime.datetime)
datetime_mock.now.return_value = FAKE_NOW
monkeypatch.setattr(datetime, "datetime", datetime_mock)
assert datetime.datetime.now() == FAKE_NOW
# the other methods are available
assert datetime.datetime.fromisoformat("2020-03-01T00:00:00") == datetime.datetime(2020, 3, 1, 0, 0, 0)
这里使用@pytest.fixture
方法
import datetime
from unittest.mock import MagicMock
import pytest
FAKE_NOW = datetime.datetime(2020, 3, 11, 14, 0, 0)
@pytest.fixture()
def mock_datetime_now(monkeypatch):
datetime_mock = MagicMock(wraps=datetime.datetime)
datetime_mock.now.return_value = FAKE_NOW
monkeypatch.setattr(datetime, "datetime", datetime_mock)
def test_datetime_now2(mock_datetime_now):
assert datetime.datetime.now() == FAKE_NOW
assert datetime.datetime.fromisoformat("2020-03-01T00:00:00") == datetime.datetime(2020, 3, 1, 0, 0, 0)
是否可以只替换now
方法?这是可行的,但如果您执行“从日期时间导入日期时间”,则不可行。在这里查看详细信息:我能够调整这个答案并修补utcnow
修补程序的来源?您错过导入了吗?从unittest.mock import patch@sashkYou也错过了导入contextmanager:从contextlib导入contextmanager
您忘记导入MagicMock
。所以按原样编码是行不通的。谢谢你的评论!我修复了它。这将破坏使用isinstance(value,datetime.datetime)
的代码,例如,tortoise orm。
from unittest.mock import MagicMock
def test_datetime_now(monkeypatch):
import datetime
FAKE_NOW = datetime.datetime(2020, 3, 11, 14, 0, 0)
datetime_mock = MagicMock(wraps=datetime.datetime)
datetime_mock.now.return_value = FAKE_NOW
monkeypatch.setattr(datetime, "datetime", datetime_mock)
assert datetime.datetime.now() == FAKE_NOW
# the other methods are available
assert datetime.datetime.fromisoformat("2020-03-01T00:00:00") == datetime.datetime(2020, 3, 1, 0, 0, 0)
import datetime
from unittest.mock import MagicMock
import pytest
FAKE_NOW = datetime.datetime(2020, 3, 11, 14, 0, 0)
@pytest.fixture()
def mock_datetime_now(monkeypatch):
datetime_mock = MagicMock(wraps=datetime.datetime)
datetime_mock.now.return_value = FAKE_NOW
monkeypatch.setattr(datetime, "datetime", datetime_mock)
def test_datetime_now2(mock_datetime_now):
assert datetime.datetime.now() == FAKE_NOW
assert datetime.datetime.fromisoformat("2020-03-01T00:00:00") == datetime.datetime(2020, 3, 1, 0, 0, 0)