python - 如何卡住 datetime.now 以进行单元测试

标签 python django python-unittest django-testing

我有一个使用函数返回默认日期时间的模型:

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< 时仍然使用今天的日期.

我该如何纠正这个问题?

最佳答案

这不起作用的原因是因为您调用了函数。因此,这意味着 datetime 在类被解释时被评估,所以这基本上是在您启动服务器时。在那一刻卡住枪还没有激活。

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

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

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

def <b>quarter_results_date_first</b>():
    return quarter_results_date(1)

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

请注意,default=quarter_results_date_first 没有使用括号,因此我们传递了对该函数的引用,而不是日期时间值。

关于python - 如何卡住 datetime.now 以进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62837395/

相关文章:

python - 嵌套序列化器未显示

python - 无法使用 pytest 运行测试,找不到模块

python - 从 RaspberryPi 传感器向 Django 后端发送数据(频率、批量更新、鲁棒性)

Python:转换字典中的元组列表

python - 模拟 __call__ 属性不会模拟该函数

python - 如何在 Python 中模拟 cx_Oracle 游标

python - 可以解压类型提示吗?或其解决方法?

python - Django Rest Framework 不允许我拥有多个权限

python - 在 Python 中循环遍历列表,增加值,同时在每次迭代时遍历列表

python - TextBlob 翻译有限制吗?