gpt4 book ai didi

python - 模拟 default=timezone.now 用于单元测试

转载 作者:太空狗 更新时间:2023-10-29 17:05:01 25 4
gpt4 key购买 nike

我正在尝试为执行大量日期时间操作的 Django 应用程序编写单元测试。我已经安装了mock猴子修补 django 的 timezone.now 用于我的测试。

虽然我能够在正常调用时成功模拟 timezone.now(实际上是在我的代码中调用 timezone.now(),但我无法模拟它适用于使用 default=timezone.nowDateTimeField 创建的模型。


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

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)

我的单元测试是这样的:

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) 没有通过。

我如何模拟 timezone.now,以便即使我模型中的 default=timezone.now 也能创建模拟时间?


编辑

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

最佳答案

这是一种您可以使用的方法,它不需要更改您的非测试代码。只需修补要影响的字段的 default 属性。例如--

field = User._meta.get_field('timestamp')
mock_now = lambda: datetime(2010, 1, 1)
with patch.object(field, 'default', new=mock_now):
# Your code here

您可以编写辅助函数来简化此过程。例如下面的代码--

@contextmanager
def patch_field(cls, field_name, dt):
field = cls._meta.get_field(field_name)
mock_now = lambda: dt
with patch.object(field, 'default', new=mock_now):
yield

会让你写--

with patch_field(User, 'timestamp', dt):
# Your code here

同样,您可以编写助手上下文管理器来一次修补多个字段。

关于python - 模拟 default=timezone.now 用于单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18924869/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com