如何在一个文件中模拟日期时间?

时间:2018-06-11 08:13:40

标签: python mocking

我有两个文件,我使用datetime。有没有办法在一个文件而不是另一个文件中模拟它?以下是我看到一种奇怪行为的例子。

文件:test_file_one.py

import datetime as dt
def print_datetime():
    print 'First: {}'.format(dt.datetime.utcnow())

文件:test_file_two.py

import datetime as dt
def print_datetime():
    print 'Second: {}'.format(dt.datetime.utcnow())

文件:main.py

import test_file_one as first
import test_file_two as second
import mock
from datetime import datetime, timedelta

@mock.patch('test_file_one.dt.datetime')
def main(mock_datetime):
    mock_datetime.utcnow.return_value = datetime.utcnow() + timedelta(days=1)
    first.print_datetime()
    second.print_datetime()

if __name__ == '__main__':
    main()

输出

First: 2018-06-12 08:12:43.838243
Second: 2018-06-12 08:12:43.838243

如您所见,两者都返回被嘲笑的相同日期时间。

  1. 为什么两个都被嘲笑?
  2. 如何将模拟限制为一个文件?

2 个答案:

答案 0 :(得分:2)

您只需将要调用的结果添加到side_effect

即可
mock_datetime.utcnow.side_effect = [datetime.utcnow() + timedelta(days=1), datetime.utcnow() + timedelta(days=2)] 

答案 1 :(得分:1)

我建议你减少嘲笑的范围。

现在,您将使用装饰器@mock.patch('test_file_one.dt.datetime')

将模拟应用于整个方法

相反,你可以尝试类似的东西:

def main(mock_datetime):
    with mock.patch('test_file_one.dt.datetime') as mock_datetime:
        mock_datetime.utcnow.return_value = datetime.utcnow() + timedelta(days=1)
        first.print_datetime()

    second.print_datetime()

作为替代方案,您可以使用fake_time库中的libfaketime-tz-wrapper方法。

然后你的方法就像:

from libfaketime_tz_wrapper import fake_time

def main(mock_datetime):
    with fake_time(datetime.utcnow() + timedelta(days=1)):
        first.print_datetime()

    second.print_datetime()

我没有测试我的建议是否有效,但我在过去的1。5年里一直在使用fake_time,而且在这样的问题上似乎非常少。