为了账号安全,请及时绑定邮箱和手机立即绑定

如何冻结 datetime.now 以进行单元测试

如何冻结 datetime.now 以进行单元测试

ITMISS 2023-03-01 16:54:19
我有一个使用函数返回默认日期时间的模型: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。我该如何纠正这个问题?
查看完整描述

1 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

这不起作用的原因是因为您调用了该函数。因此,这意味着datetime在解释类时对 进行求值,所以这基本上是在您启动服务器时进行的。在那一刻,冷冻枪还没有激活。


因此,这也意味着如果您稍后运行服务器一段时间,并且年份增加,它仍将使用旧值。


您可以将可调用对象传递给默认值,从而使用辅助函数,例如:


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,因此我们将引用传递给函数,而不是日期时间值。


查看完整回答
反对 回复 2023-03-01
  • 1 回答
  • 0 关注
  • 160 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号