如何在用于单元测试的类方法中模拟 python 的 datetime.now()?

新手上路,请多包涵

我正在尝试为具有以下方法的类编写测试:

 import datetime
import pytz

class MyClass:
    def get_now(self, timezone):
        return datetime.datetime.now(timezone)

    def do_many_things(self, tz_string='Europe/London'):
        tz = pytz.timezone(tz_string)
        localtime_now = self.get_now(tz)
        ...
        return things

我想测试它,为此我需要确保 datetime.datetime.now() 调用返回可预测的内容。

我已经阅读了很多在测试中使用 Mock 的示例,但没有找到任何我需要的东西,而且我不知道如何在我的测试中使用它。

我将 get_now() 方法分开,以防它更容易模拟它,而不是 datetime.datetime.now() ,但我仍然很难过。关于如何使用 Mock 为此编写单元测试有什么想法吗? (这一切都在 Django 中,fwiw;我不确定这在这种情况下是否有所不同。)

原文由 Phil Gyford 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 530
2 个回答

你可以使用 freezegun

 from freezegun import freeze_time

def test():
    assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)
    with freeze_time("2012-01-14"):
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
    assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)

它基本上 datetime 模块调用。

原文由 Jocelyn delalande 发布,翻译遵循 CC BY-SA 3.0 许可协议

您将创建一个返回特定日期时间的函数,本地化为传入的时区:

 import mock

def mocked_get_now(timezone):
    dt = datetime.datetime(2012, 1, 1, 10, 10, 10)
    return timezone.localize(dt)

@mock.patch('path.to.your.models.MyClass.get_now', side_effect=mocked_get_now)
def your_test(self, mock_obj):
    # Within this test, `MyClass.get_now()` is a mock that'll return a predictable
    # timezone-aware datetime object, set to 2012-01-01 10:10:10.

这样您就可以测试生成的时区感知日期时间是否得到正确处理;其他地方的结果应该显示正确的时区,但会有可预测的日期和时间。

您在模拟时使用 mocked_get_now 函数作为副作用 get_now ;每当代码调用 get_now 调用被 mock 记录, 并且 mocked_get_now 被调用,它的返回值被用作调用 get_now

原文由 Martijn Pieters 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题