模拟默认= timezone.now用于单元测试 [英] Mocking default=timezone.now for unit tests

查看:103
本文介绍了模拟默认= timezone.now用于单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为执行大量日期时间操作的django应用编写单元测试.我已经安装了 mock 来对django的timezone.now补丁进行测试.

I'm trying to write unit tests for a django app that does a lot of datetime operations. I have installed mock to monkey patch django's timezone.now for my tests.

虽然正常调用时可以成功模拟timezone.now(实际上在我的代码中调用了timezone.now(),但是对于使用DateTimeFielddefault=timezone.now创建的模型,我却不能对其进行模拟.

While I am able to successfully mock timezone.now when it is called normally (actually calling timezone.now() in my code, I am not able to mock it for models that are created with a DateTimeField with default=timezone.now.

我有一个User模型,该模型包含以下内容:

I have a User model that contains the following:

from django.utils import timezone
...
timestamp = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(default=timezone.now)
...
def save(self, *args, **kwargs):
    if kwargs.pop('modified', True):
        self.modified = timezone.now()
    super(User, self).save(*args, **kwargs)


我的单元测试如下:


My unit test looks like this:

from django.utils import timezone

def test_created(self):
    dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
    with patch.object(timezone, 'now', return_value=dt):
        user = User.objects.create(username='test')
        self.assertEquals(user.modified, dt)
        self.assertEquals(user.timestamp, dt)


assertEquals(user.modified, dt)通过,但assertEquals(user.timestamp, dt)没有通过.


assertEquals(user.modified, dt) passes, but assertEquals(user.timestamp, dt) does not.

如何模拟timezone.now,以便模型中的default=timezone.now都可以创建模拟时间?

How can I mock timezone.now so that even default=timezone.now in my models will create the mock time?

修改

我知道我可以更改单元测试以通过我选择的timestamp(可能是由模拟的timezone.now生成的)......很好奇是否有办法避免这种情况.

I know that I could just change my unit test to pass a timestamp of my choice (probably generated by the mocked timezone.now)... Curious if there is a way that avoids that though.

推荐答案

我本人只是遇到了这个问题.问题在于,在模拟补丁修补时区模块之前已加载模型,因此在计算表达式default=timezone.now时,会将default kwarg设置为实际的timezone.now函数.

I just ran into this issue myself. The problem is that models are loaded before mock has patched the timezone module, so at the time the expression default=timezone.now is evaluated, it sets the default kwarg to the real timezone.now function.

解决方案如下:

class MyModel(models.Model):
    timestamp = models.DateTimeField(default=lambda: timezone.now())

这篇关于模拟默认= timezone.now用于单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆