简体   繁体   中英

How to freeze datetime.now for unit testing

I have a model that uses a function to return a default datetime:

class Company(models.Model):
    q1_results_date = models.DateField(
        verbose_name='Q1 financial results',
        default=quarter_results_date(1),
        blank=False,
        null=False,
    )

def quarter_results_date(month):
    return datetime.datetime(
        datetime.datetime.now().year,
        month,
        calendar.monthrange(datetime.datetime.now().year, month)[1]
    )

I want to unit test this, which requires me to set datetime.now() to a known value. To do this I am using freezegun.freeze_time :

def test_quarter_results_date(self):
    with freeze_time("2012-01-14"):
        print('check datetime.now()', datetime.now())
        c = Company.objects.create()
    ...

However, although the print statement shows 2012-01-14 , the datetime is not frozen as it still uses today's date when evaluating c1.q1_results_date .

How can I correct this?

The reason that this will not work is because you call the function. This thus means the datetime is evaluated when the class is interpreted, so this is basically when you start the server. At that moment the freezegun is not yet active.

This thus also means that if you later run the server for some long time, and the year gets incremented, it will still use the old value.

You can pass a callable to the default value, and thus use a helper function for example:

def quarter_results_date(month):
    yr = datetime.datetime.now().year
    __, dy = calendar.monthrange(yr, month)
    return datetime.datetime(
        yr,
        month,
        dy
    )

def ():
    return quarter_results_date(1)

class Company(models.Model):
    q1_results_date = models.DateField(
        verbose_name='Q1 financial results',
        default=,
        blank=False,
        null=False,
    )

Note that no parenthesis are used for the default=quarter_results_date_first , so we pass a reference to the function, not a datetime value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM