J'ai le ci-dessous:
from datetime import datetime
def get_report_month_key():
month_for_report = datetime.utcnow()
return month_for_report.strftime("%Y%m")
Comment me moquer de datetime.utcnow () pour pouvoir écrire un test unitaire sur cette fonction?
J'ai essayé de lire ceci one mais je suis incapable de le faire fonctionner pour moi sur utcnow ()
dans votre fichier de test:
from yourfile import get_report_month_key
import mock
import unittest
from datetime import datetime
class TestCase(unittest.TestCase):
@mock.patch('yourfile.datetime')
def test_dt(self, mock_dt):
mock_dt.utcnow = mock.Mock(return_value=datetime(1901, 12, 21))
r = get_report_month_key()
self.assertEqual('190112', r)
La réponse acceptée par dasjotre fonctionne si vous ne créez aucune instance datetime
dans le module que vous testez. Si vous essayez de créer un datetime
, il créera un objet fictif au lieu de celui avec les méthodes attendues sur un objet standard datetime
. En effet, cela remplace toute la définition de classe par un faux. Au lieu de cela, vous pouvez utiliser une approche similaire pour créer la définition simulée en utilisant datetime
comme base.
mymodule.py
from datetime import datetime
def after_y2k():
y2k = datetime(2000, 1, 1)
return y2k < datetime.utcnow()
test_mymodule.py
import unittest
import datetime
from mock import patch, Mock
import mymodule
from mymodule import after_y2k
class ModuleTests(unittest.TestCase):
@patch.object(mymodule, 'datetime', Mock(wraps=datetime.datetime))
def test_after_y2k_passes(self):
# Mock the return and run your test (Note you are doing it on your module)
mymodule.datetime.utcnow.return_value = datetime.datetime(2002, 01, 01)
self.assertEqual(True, after_y2k())
mymodule.datetime.utcnow.return_value = datetime.datetime(1999, 01, 01)
self.assertEqual(False, after_y2k())
@patch('mymodule.datetime')
def test_after_y2k_fails(self, mock_dt):
# Run your tests
mock_dt.utcnow = Mock(return_value=datetime.datetime(2002, 01, 01))
self.assertEqual(True, after_y2k())
# FAILS!!! because the object returned by utcnow is a MagicMock w/o
# datetime methods like "__lt__"
mock_dt.utcnow = Mock(return_value=datetime.datetime(1999, 01, 01))
self.assertEqual(False, after_y2k())
Ce qui fonctionne également lors de la correction des modules Python intégrés s'avère être compliqué (comme avec datetime
, voir par exemple https://solidgeargroup.com/mocking-the- time ou https: // nedbatchelder. com/blog/201209/mocking_datetimetoday.html ou https://Gist.github.com/rbarrois/5430921 ) encapsule la fonction dans une fonction personnalisée pouvant ensuite être facilement corrigée.
Donc, au lieu d’appeler datetime.datetime.utcnow()
, vous utilisez une fonction comme
import datetime
def get_utc_now():
return datetime.datetime.utcnow()
Ensuite, patcher celui-ci est aussi simple que
import datetime
# use whatever datetime you need here
fixed_now = datetime.datetime(2017, 8, 21, 13, 42, 20)
with patch('your_module_name.get_utc_now', return_value=fixed_now):
# call the code using get_utc_now() here
pass
L'utilisation du décorateur patch
à la place du gestionnaire de contexte fonctionnerait de la même manière.
Vous pouvez essayer d'utiliser le module freezetime.
from yourfile import get_report_month_key
from freezegun import freeze_time
import unittest
class TestCase(unittest.TestCase):
@freeze_time('2017-05-01')
def get_report_month_key_test():
get_report_month_key().should.equal('201705')