It’s not so rare thing to freeze time in tests and for that task I’m using freezegun and it works nice almost every time:
from freezegun import freeze_time
def test_get_date():
with freeze_time("2016.1.1"):
assert get_date() == datetime(2016, 1, 1)
But not with GAE datastore. Assume that we have a model Document
with created_at = db.DateTimeProperty(auto_now_add=True)
, so test like:
from freezegun import freeze_time
def test_created_at():
with freeze_time('2016.1.1'):
doc = Document()
doc.put()
assert doc.created_at == datetime(2016, 1, 1)
Will fail with:
BadValueError: Unsupported type for property created_at: <class 'freezegun.api.FakeDatetime'>
But it can be easily fixed if we monkey patch GAE internals:
from contextlib import contextmanager
from google.appengine.api import datastore_types
from mock import patch
from freezegun import freeze_time as _freeze_time
from freezegun.api import FakeDatetime
@contextmanager
def freeze_time(*args, **kwargs):
with patch('google.appengine.ext.db.DateTimeProperty.data_type',
new=FakeDatetime):
datastore_types._VALIDATE_PROPERTY_VALUES[FakeDatetime] = \
datastore_types.ValidatePropertyNothing
datastore_types._PACK_PROPERTY_VALUES[FakeDatetime] = \
datastore_types.PackDatetime
datastore_types._PROPERTY_MEANINGS[FakeDatetime] = \
datastore_types.entity_pb.Property.GD_WHEN
with _freeze_time(*args, **kwargs):
yield
And now it works!