Skip to content Skip to sidebar Skip to footer

How To Mock Python's Datetime.now() In A Class Method For Unit Testing?

I'm trying to write tests for a class that has methods like: import datetime import pytz class MyClass: def get_now(self, timezone): return datetime.datetime.now(timez

Solution 1:

You could use freezegun :

from freezegun import freeze_time

def test():
    assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)
    with freeze_time("2012-01-14"):
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
    assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)

It basically mocks datetime module calls.

Solution 2:

You'd create a function that returns a specific datetime, localized to the timezone passed in:

import mock

defmocked_get_now(timezone):
    dt = datetime.datetime(2012, 1, 1, 10, 10, 10)
    return timezone.localize(dt)

@mock.patch('path.to.your.models.MyClass.get_now', side_effect=mocked_get_now)defyour_test(self, mock_obj):
    # Within this test, `MyClass.get_now()` is a mock that'll return a predictable# timezone-aware datetime object, set to 2012-01-01 10:10:10.

That way you can test if the resulting timezone-aware datetime is correctly being handled; results elsewhere should show the correct timezone but will have a predictable date and time.

You use the mocked_get_now function as a side-effect when mocking get_now; whenever code calls get_now the call is recorded by mock, andmocked_get_now is called, and it's return value used as the value returned to the caller of get_now.

Solution 3:

I'm using date, but the same idea should work for datetime:

class SpoofDate(date):
    def __new__(cls, *args, **kwargs):
        returndate.__new__(date, *args, **kwargs)

...

from mock import patch

@patch('some.module.date', SpoofDate)deftestSomething(self):
    SpoofDate.today = classmethod(lambda cls : date(2012, 9, 24))

Where some.module imports date. Patch is replacing the imported date with SpoofDate, which you can then redefine to do whatever you want.

Solution 4:

I would use the helpers from the 'testfixtures' package to mock out the datetime class you're calling now() on:

http://packages.python.org/testfixtures/datetime.html#datetimes

That way, you can test all the cases you have, all the time.

Solution 5:

Having asked this question originally...

As @Jocelyn delalande suggested, I've been happily using freezegun for years now.

Another option is python-libfaketime, which can be much faster than freezegun, but doesn't work on Windows and sounds a bit fiddly.

A newer option is time-machine, introduced in this blog post that compares the three options.

Post a Comment for "How To Mock Python's Datetime.now() In A Class Method For Unit Testing?"