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:
fromfreezegunimportfreeze_timedeftest_get_date():withfreeze_time("2016.1.1"):assertget_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:
fromfreezegunimportfreeze_timedeftest_created_at():withfreeze_time('2016.1.1'):doc=Document()doc.put()assertdoc.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:
fromcontextlibimportcontextmanagerfromgoogle.appengine.apiimportdatastore_typesfrommockimportpatchfromfreezegunimportfreeze_timeas_freeze_timefromfreezegun.apiimportFakeDatetime@contextmanagerdeffreeze_time(*args,**kwargs):withpatch('google.appengine.ext.db.DateTimeProperty.data_type',new=FakeDatetime):datastore_types._VALIDATE_PROPERTY_VALUES[FakeDatetime]= \
datastore_types.ValidatePropertyNothingdatastore_types._PACK_PROPERTY_VALUES[FakeDatetime]= \
datastore_types.PackDatetimedatastore_types._PROPERTY_MEANINGS[FakeDatetime]= \
datastore_types.entity_pb.Property.GD_WHENwith_freeze_time(*args,**kwargs):yield
And now it works!