在上下文中模拟计时,以使用带有auto_now_add = True的字段DateTimeField创建模型

问题描述 投票:3回答:2

我想模拟计时,以便能够在我的测试中用DateTimeFieldauto_now_add=True类型的字段设置一定的时间,例如:

class MyModel:
    ...
    created_at = models.DateTimeField(auto_now_add=True)
    ...


class TestMyModel(TestCase):
    ...
    def test_something(self):
        # mock current time so that `created_at` be something like 1800-02-09T020000
        my_obj = MyModel.objects.create(<whatever>)
        # and here my_obj.created_at == 1800-02-09T000000

我知道当前的日期是always用于这种类型的字段,这就是为什么我正在寻找一种替代方法来模拟系统时序,但只是在一个上下文中。

我尝试了一些方法,例如,用freeze_time创建一个上下文但是没有用:

with freeze_now("1800-02-09"):
    MyModel.objects.create(<whatever>)
    # here the created_at doesn't fit 1800-02-09

我想,这是因为当auto_now_add=True创建对象的方式背后的机制。

我不想删除auto_now_add=True并使用默认值。

有没有办法我们可以模拟时间,以便我们可以做到这一点,这种领域在某些情况下得到我想要的时间?

我正在使用Django 1.9.6Python 3.4

python django testing mocking timing
2个回答
10
投票

好的,我找到了一个解决方案,它基于mock

def mock_now():
    return <mock time>

class TestMyModel(TestCase):
    ...
    @mock.patch('django.utils.timezone.now', mock_now)
    def test_as_decorator(self):
        ...
        my_obj = MyModel.objects.create(<whatever>)
        ...
         # here the created_at field has the mocking time :)

    def test_as_context_manager(self):
         mocked_dt = datetime.datetime(2015, 9, 3, 11, 15, 0)
         with mock.patch('django.utils.timezone.now', mock.Mock(return_value=mocked_dt)):
             my_obj = MyModel.objects.create(<whatever>)
             # here the created_at field has the mocking time :)

0
投票

扩展@trinchets答案,这里是上下文管理器,

from datetime import timedelta
from django.utils import timezone
from mock import patch, Mock


last_week = timezone.now() - timedelta(weeks=1)
with patch('django.utils.timezone.now', Mock(return_value=last_week)):
    # Make your models/factories

# Carry on with normal time
© www.soinside.com 2019 - 2024. All rights reserved.