Python test using mock with datetime.utcnow()



我 utils.py 中有以下函数,基本上计算从 1970 年到当前时间的秒数:

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

我想在该功能上运行一个测试用例,但它取决于时间,所以我寻找解决方案并在 SO link 上偶然发现了这个问题,我试图在我的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()

我在控制台中测试了它的结果:

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

它返回了

1566895932.703618

但是当我运行测试时,我得到了断言错误:

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

我做错了什么?

任何帮助将不胜感激!

编辑:

感谢 ipaleka 对正在发生的事情的解释,因为我无法在带有 mock 的类中更改 python 构建,所以我需要创建一个 utcnow(( 的自定义类来返回 test_utils.py 中的自定义时间:

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

并将测试功能更改为:

def test_get_utc_timestamp(self):
result = get_utc_timestamp()
self.assertEqual(result, 1566895932.703618)

您没有做任何与引用的 SO 答案相关的错误,但该示例在您同时使用utcnowdatetime(用于创建epoch变量(时仅使用utcnow函数。

当您修补模块时,每次调用子模块、方法或其函数都会创建一个 MagicMock。当您调用epoch = datetime.datetime(1970, 1, 1)时会发生这种情况。所以基本上你是在比较MagicMock和float。

您应该同时修补它们,或者只修补utcnow

@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)

最新更新