2016-05-17 2 views
2

Je voudrais railler le calendrier afin que être en mesure de définir certain temps à un champ de type DateTimeField avec auto_now_add=True lors de mes tests, par exemple:calendrier Mock dans un contexte pour créer des modèles avec un DateTimeField de terrain avec 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 

Je suis au courant de la date actuelle est always utilisé pour ce type de champs, c'est pourquoi je suis à la recherche d'une alternative pour se moquer d'une certaine manière la synchronisation du système, mais seulement dans un contexte.

J'ai essayé quelques approches, par exemple, la création d'un contexte avec freeze_time mais ne fonctionne pas:

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

Ofc je suppose, cela est dû à la machine derrière la façon dont il est créé l'objet avec auto_now_add=True. Je ne veux pas supprimer auto_now_add=True et utiliser les valeurs par défaut.

Y a-t-il un moyen de se moquer du timing afin que nous puissions faire en sorte que ce type de champ obtienne le temps que je veux dans un certain contexte?

J'utilise Django 1.9.6 et Python 3.4

+0

Les versions de Django et Python? – theWanderer4865

+0

Vous pourriez probablement se moquer de la méthode pre_save sur le champ date-heure - un peu icky mais bon, pas vrai? – theWanderer4865

+0

J'utilise Django 1.9.6 et Python 3.4 – trinchet

Répondre

6

D'accord, j'ai trouvé une solution, elle est basée sur 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

Développant @trinchets réponse, ici il est en tant que gestionnaire de contexte,

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