Python: How do I mock datetime.utcnow()?
我有以下内容:
1 2 3 4 5 | from datetime import datetime def get_report_month_key(): month_for_report = datetime.utcnow() return month_for_report.strftime("%Y%m") |
如何模拟datetime.utcnow()以便我可以在此函数上编写单元测试?
尝试读这个,但我无法让它在utcnow()上为我工作
在您的测试文件中:
1 2 3 4 5 6 7 8 9 10 11 12 | 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) |
如果您不在要测试的模块中创建任何
mymodule.py
1 2 3 4 5 | from datetime import datetime def after_y2k(): y2k = datetime(2000, 1, 1) return y2k < datetime.utcnow() |
test_mymodule.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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()) |
修补内置Python模块时的效果也很复杂(与
因此,您不必调用
1 2 3 4 5 | import datetime def get_utc_now(): return datetime.datetime.utcnow() |
然后,修补这个就像这样简单
1 2 3 4 5 6 7 | 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 |
使用
您可以尝试使用freezetime模块。
1 2 3 4 5 6 7 8 9 | 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') |
如果您的代码在另一个文件中,则需要修改导入发生的位置(让我们调用您的文件file1.py):
1 2 3 4 5 6 7 | from file1 import get_report_month_key import mock @mock.patch("get_report_month_key.datetime.utcnow") def test_get_report_month_key(mock_utcnow): mock_utcnow.return_value ="your value" assert get_report_month_key() =="your expected value" |
当然,我会用unittest框架包装它。