0

I have the following function in my utils.py basically count the seconds from 1970 till curent time:

import datetime

def get_utc_timestamp():
    d = datetime.datetime.utcnow()
    epoch = datetime.datetime(1970, 1, 1)
    t = (d - epoch).total_seconds()

    return t

I want to run a test case on that function but it's time dependent so i looked for a solution and stumble upon this question on SO link i tried to apply it in my test_utils.py:

import unittest
from utils import *
from unittest import mock
import datetime

class TestUtils(unittest.TestCase):

    @mock.patch('utils.datetime.datetime')
    def test_get_utc_timestamp(self, mock_dt):
        mock_dt.utcnow = mock.Mock(return_value = datetime.datetime(2019, 8, 27, 8, 52, 12, 703618))
        result = get_utc_timestamp()
        self.assertEqual(result, 1566895932.703618)

if __name__ == '__main__':
    unittest.main()

I tested the result of it in the console:

d = datetime.datetime(2019, 8, 27, 8, 52, 12, 703618)
epoch = datetime.datetime(1970, 1, 1)
t = (d - epoch).total_seconds()

return t

And it returned

1566895932.703618

But when i run the test i got AssertionError:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/unittest/mock.py", line 1179, in patched
    return func(*args, **keywargs)
  File "/app/tests/test_utils.py", line 15, in test_get_utc_timestamp
    self.assertEqual(result, 1566895932.703618)
AssertionError: <MagicMock name='datetime().__sub__().total_seconds()' id='140475857850040'> != 1566895932.703618

What am i doing wrong ?

Any help would be appreciate!

EDIT:

thank ipaleka for the explanation on what going on, since i can't change python built - in class with mock so i need to make a custom class of utcnow() to return the custom time in test_utils.py:

class NewDate(datetime.datetime):
    @classmethod
    def utcnow(cls):
        return cls(2019, 8, 27, 8, 52, 12, 703618)

datetime.datetime = NewDate

and change test function to:

def test_get_utc_timestamp(self):
    result = get_utc_timestamp()
    self.assertEqual(result, 1566895932.703618)
Linh Nguyen
  • 3,452
  • 4
  • 23
  • 67
  • Could you try replacing `@mock.patch('utils.datetime.datetime')` by `@mock.patch('datetime.datetime')`? You might be "patching the wrong name" (see https://docs.python.org/3/library/unittest.mock.html#where-to-patch) – Pierre V. Aug 27 '19 at 09:42
  • i replaced it and it still return AssertionError, my tests folder which contain test_utils.py is the same top level as utils.py – Linh Nguyen Aug 27 '19 at 09:44

1 Answers1

0

You're not doing anything wrong related to referenced SO answer, but that example uses only utcnow function while you're using both utcnow and datetime (for creating epoch variable).

When you patch a module then every call to submodule, method or its function creates a MagicMock. That happens when you called epoch = datetime.datetime(1970, 1, 1). So basically you're comparing MagicMock to float.

You should either patch them both or patch just the utcnow with:

@mock.patch('utils.datetime.datetime.utcnow')
def test_get_utc_timestamp(self, mock_dt):
    mock_dt.return_value = datetime.datetime(2019, 8, 27, 8, 52, 12, 703618)
    result = get_utc_timestamp()
    self.assertEqual(result, 1566895932.703618)
ipaleka
  • 3,745
  • 2
  • 13
  • 33
  • it can't seem to set value of python built-in 'datetime.datetime' TypeError: can't set attributes of built-in/extension type 'datetime.datetime' – Linh Nguyen Aug 27 '19 at 10:05
  • nvm i just replace base datetime.datetime.utc class with custom return , edited in description. Thank for the explain! – Linh Nguyen Aug 27 '19 at 10:14