2016-05-17 44 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