2016-05-17 56 views
2

我想嘲笑时刻,以便能够在我的测试如设置一定的时间来DateTimeField类型的字段与auto_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 

OFC我想,这是由于机器背后是如何创建与对象auto_now_add=True。我不想删除auto_now_add=True并使用默认值。

有没有一种方法可以模拟计时,以便我们可以做到这样的领域在特定环境下获得我想要的时间?

我使用Django 1.9.6Python 3.4

+0

Django和Python版本? – theWanderer4865

+0

你也许可以在日期时间字段上模拟pre_save方法 - 有点恶心,但是,嘿,时间正确吗? – theWanderer4865

+0

我正在使用Django 1.9.6和Python 3.4 – trinchet

回答

6

好吧,我已经找到了解决方案,它是基于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