簡體   English   中英

如何凍結 datetime.now 進行單元測試

[英]How to freeze datetime.now for unit testing

我有一個 model 使用 function 返回默認日期時間:

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

我想對此進行單元測試,這需要我將 datetime.now() 設置為已知值。 為此,我使用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()
    ...

但是,盡管print語句顯示2012-01-14 ,但日期時間並未凍結,因為它在評估c1.q1_results_date時仍使用今天的日期。

我該如何糾正?

這不起作用的原因是因為您調用了 function。 因此,這意味着在解釋datetime時會評估日期時間,所以這基本上是在您啟動服務器時。 在那一刻,冷凍槍尚未激活。

因此,這也意味着,如果您稍后運行服務器一段時間,並且年份增加,它仍將使用舊值。

您可以將可調用對象傳遞給默認值,從而使用幫助程序 function 例如:

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

def quarter_results_date_first():
    return quarter_results_date(1)

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

請注意, default=quarter_results_date_first沒有使用括號,因此我們傳遞了對 function 的引用,而不是日期時間值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM