pro*_*sev 6 python testing unit-testing sqlalchemy mocking
我在Flask应用程序中使用SQLAlchemy。在测试中,我尝试为自己的条目模拟自动时间创建和更新。但是我不明白它如何用于SQLAlchemy。例如,我尝试使用freezgun模拟 datetime创建,但是失败。例如:
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())
class ViewTestCase(AppliactionTestCase):
def test(self):
with freeze_time("2014-06-01 16:00:00"):
db.session.add(Entry())
db.session.commit()
entry = db.session.query(Entry).first()
self.assertEqual(entry.created, datetime(2014, 6, 1, 16, 0, 0))
Run Code Online (Sandbox Code Playgroud)
还有一个问题。如果需要刷新updated输入内容,如何强制保存输入内容而不进行更改?
小智 5
sqlalchemy 提供 hook sqlalchemy.eventapi 来修补查询会话。
先决条件: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())
Run Code Online (Sandbox Code Playgroud)
只需编写一个 pytest 装置来修补行创建时间:
import datetime
from flask_sqlalchemy import event
from contextlib import contextmanager
from freezegun import freeze_time
import Entry
# if you want the code be commonly used, change Entry to db.Model instead
@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
Run Code Online (Sandbox Code Playgroud)
然后编写一个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)
Run Code Online (Sandbox Code Playgroud)
如果有人使用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))
Run Code Online (Sandbox Code Playgroud)
快乐编码。
冷冻枪只有补丁datetime.datetime.now。您可以通过以下两种方式之一解决该问题:
mock.patchpatch db.func.now(),或(在我看来更简单),default=datetime.datetime.now,这样 freezegun 将正确修补它。| 归档时间: |
|
| 查看次数: |
1204 次 |
| 最近记录: |