Ich habe das Folgende:
from datetime import datetime
def get_report_month_key():
month_for_report = datetime.utcnow()
return month_for_report.strftime("%Y%m")
Wie versuche ich, datetime.utcnow () zu verspotten, damit ich einen Unit-Test für diese Funktion schreiben kann?
Ich habe versucht, dieses eine zu lesen, kann es aber bei utcnow () nicht zum Laufen bringen.
in Ihrer Testdatei:
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)
Die akzeptierte Antwort von dasjotre funktioniert, wenn Sie in dem von Ihnen getesteten Modul keine datetime
-Instanzen erstellen. Wenn Sie versuchen, eine datetime
zu erstellen, wird ein Mock-Objekt anstelle eines Objekts mit den erwarteten Methoden für ein Standardobjekt datetime
erstellt. Dies liegt daran, dass die gesamte Klassendefinition durch einen Schein ersetzt wird. Anstatt dies zu tun, können Sie einen ähnlichen Ansatz verwenden, um die gespielte Definition mithilfe von datetime
als Basis zu erstellen.
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())
Was auch beim Patchen von integrierten Python-Modulen funktioniert, erweist sich als kompliziert (wie bei datetime
, siehe zB https://solidgeargroup.com/mocking-the-time oder https: // nedbatchelder com/blog/201209/mocking_datetimetoday.html oder https://Gist.github.com/rbarrois/5430921 ) umgibt die Funktion in einer benutzerdefinierten Funktion, die dann problemlos gepatcht werden kann.
Anstatt datetime.datetime.utcnow()
aufzurufen, verwenden Sie eine Funktion wie
import datetime
def get_utc_now():
return datetime.datetime.utcnow()
Dann ist das Patchen dieses so einfach wie
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
Die Verwendung des Dekorators patch
anstelle des Kontextmanagers funktioniert ähnlich.
Sie können das freezetime-Modul verwenden.
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')