Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How do I mock datetime.utcnow()?

I have the below:

from datetime import datetime  def get_report_month_key():     month_for_report = datetime.utcnow()     return month_for_report.strftime("%Y%m")  

How do I mock datetime.utcnow() so that I can write unit test on this function?

Tried reading this one but I am unable to get it working for me on utcnow()

like image 377
Steven Yong Avatar asked May 05 '17 07:05

Steven Yong


2 Answers

in your test file:

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) 
like image 92
dasjotre Avatar answered Oct 14 '22 18:10

dasjotre


The accepted answer by dasjotre works if you don't create any datetime instances in the module you are testing. If you try to create a datetime it will create a Mock object instead of one with the expected methods on a standard datetime object. This is because it replaces the whole class definition with a mock. Instead of doing this, you can use a similar approach to create the mocked definition by using datetime as the 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()) 
like image 36
Ryan Widmaier Avatar answered Oct 14 '22 16:10

Ryan Widmaier