EDIT: Dal momento che la mia risposta è la risposta accettata qui sto aggiornando a far sapere a tutti un modo migliore è stata creata nel frattempo, la biblioteca freezegun: https://pypi.python.org/pypi/freezegun. Lo uso in tutti i miei progetti quando voglio influenzare il tempo nei test. Date un'occhiata a questo.
risposta originale:
Sostituzione roba interna come questo è sempre pericoloso perché può avere effetti collaterali sgradevoli. Quindi, quello che vuoi davvero è avere la patch della scimmia più locale possibile.
Usiamo eccellente biblioteca finta di Michael Foord: http://www.voidspace.org.uk/python/mock/ che ha un decoratore @patch
quali patch alcune funzionalità, ma la patch scimmia vive solo nel campo di applicazione della funzione di prova, e tutto ciò che viene ripristinato automaticamente dopo la funzione esaurisce la sua portata .
L'unico problema è che il modulo interno datetime
è implementato in C, quindi per impostazione predefinita non sarà possibile eseguire il patch della patch. Abbiamo risolto questo problema rendendo la nostra implementazione semplice che può essere derisa.
La soluzione totale è qualcosa di simile (l'esempio è una funzione di convalida utilizzata all'interno di un progetto Django per convalidare che una data è in futuro). Tenete conto che ho preso questo da un progetto ma ho eliminato le cose non importanti, quindi le cose potrebbero non funzionare quando copia-incolla questo, ma l'idea, spero :)
Per prima cosa definiamo il nostro molto semplice realizzazione di datetime.date.today
in un file chiamato utils/date.py
:
import datetime
def today():
return datetime.date.today()
Poi creiamo l'unittest per questo validatore in tests.py
:
import datetime
import mock
from unittest2 import TestCase
from django.core.exceptions import ValidationError
from .. import validators
class ValidationTests(TestCase):
@mock.patch('utils.date.today')
def test_validate_future_date(self, today_mock):
# Pin python's today to returning the same date
# always so we can actually keep on unit testing in the future :)
today_mock.return_value = datetime.date(2010, 1, 1)
# A future date should work
validators.validate_future_date(datetime.date(2010, 1, 2))
# The mocked today's date should fail
with self.assertRaises(ValidationError) as e:
validators.validate_future_date(datetime.date(2010, 1, 1))
self.assertEquals([u'Date should be in the future.'], e.exception.messages)
# Date in the past should also fail
with self.assertRaises(ValidationError) as e:
validators.validate_future_date(datetime.date(2009, 12, 31))
self.assertEquals([u'Date should be in the future.'], e.exception.messages)
la realizzazione finale è simile al seguente:
012.
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from utils import date
def validate_future_date(value):
if value <= date.today():
raise ValidationError(_('Date should be in the future.'))
Spero che questo aiuti
Questo è davvero il modo giusto.Questa libreria fittizia è superba. – hendrixski
Ho scritto un metodo alternativo utilizzare mock/patch con datetime: http: //www.voidspace.org.uk/python/weblog/arch_d7_2010_10_02.shtml#e1188 – fuzzyman