SQLAlchemy提供了钩子sqlalchemy.event
API来修补查询会话。
前提条件: flask-sqlalchemy,pytest,freezengun,contextlib
使用@prokoptesev所使用的flask-sqlalchemy示例:
class Entry(db.Model):
__tablename__ = 'entries'
created = db.Column(db.DateTime(), default=db.func.now())
updated = db.Column(db.DateTime(), default=db.func.now(), onupdate=db.func.now())
只需编写pytest fixtures以修改行创建时间:
import datetime
from flask_sqlalchemy import event
from contextlib import contextmanager
from freezegun import freeze_time
import Entry
@contextmanager
def patch_time(time_to_freeze, tick=True):
with freeze_time(time_to_freeze, tick=tick) as frozen_time:
def set_timestamp(mapper, connection, target):
now = datetime.datetime.now()
if hasattr(target, 'created'):
target.created = now
if hasattr(target, 'updated'):
target.updated = now
event.listen(Entry, 'before_insert', set_timestamp,
propagate=True)
yield frozen_time
event.remove(Entry, 'before_insert', set_timestamp)
@pytest.fixture(scope='function')
def patch_current_time():
return patch_time
然后编写一个 Pytest 类型的测试用例:
def test_patch_insert_time(patch_current_time, assertions):
with patch_current_time("2014-06-01 16:00:00", tick=False):
db.session.add(Entry())
db.session.commit()
entry = db.session.query(Entry).first()
assert entry.created == datetime(2014, 6, 1, 16, 0, 0)
如果有人使用unittools
或其他测试包,您也可以直接使用patch_time函数:
class ViewTestCase(AppliactionTestCase):
def test(self):
with patch_time("2014-06-01 16:00:00", tick=False):
db.session.add(Entry())
db.session.commit()
entry = db.session.query(Entry).first()
self.assertEqual(entry.created, datetime(2014, 6, 1, 16, 0, 0))
愉快编码。
default=datetime.datetime.now
,datetime会被修补,但在保存的模型中,“created”会返回当前时间。 - prokoptsevdb.func.now
? 如果我错了,请纠正我。db.func.now
是保存模型时的数据库函数。也许修补它不正确? - prokoptsevEntry
类相对于哪里? - Patrick Collins