Freeze time in tests even with GAE datastore

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()
        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

def freeze_time(*args, **kwargs):
    with patch('google.appengine.ext.db.DateTimeProperty.data_type',
        datastore_types._VALIDATE_PROPERTY_VALUES[FakeDatetime] = \
        datastore_types._PACK_PROPERTY_VALUES[FakeDatetime] = \
        datastore_types._PROPERTY_MEANINGS[FakeDatetime] = \
        with _freeze_time(*args, **kwargs):

And now it works!

comments powered by Disqus