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

How to mock python's datetime.now() in a class method for unit testing?

我正在尝试为一个类编写测试,该类的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
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()调用返回可预测的结果。

我已经阅读了很多在测试中使用模拟的例子,但是还没有找到与我需要的完全相同的东西,而且我也不知道如何在测试中使用它。

我将get_now()方法分离出来,以防更容易模仿它,而不是datetime.datetime.now(),但我仍然感到困惑。对于如何使用mock编写这个单元测试有什么想法吗?(这都是在南威省的Django,我不确定这是否会对本案产生影响。)


你可以使用Freezegun:

1
2
3
4
5
6
7
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模块调用。


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

1
2
3
4
5
6
7
8
9
10
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.

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

当模拟get_now时,使用mocked_get_now函数作为副作用;当代码调用get_now时,调用由mock记录,调用mocked_get_now,其返回值用作返回给get_now调用方的值。


我使用的是date,但同样的想法也适用于datetime

1
2
3
class SpoofDate(date):
    def __new__(cls, *args, **kwargs):
        return date.__new__(date, *args, **kwargs)

1
2
3
4
5
from mock import patch

@patch('some.module.date', SpoofDate)
def testSomething(self):
    SpoofDate.today = classmethod(lambda cls : date(2012, 9, 24))

其中some.module进口date。补丁程序正在将导入的date替换为SpoofDate,然后您可以重新定义它来执行您想要的任何操作。


我将使用"testfactures"包中的帮助程序模拟您现在调用的日期时间类():

http://packages.python.org/testfactures/datetime.html日期时间

这样,您就可以随时测试您拥有的所有案例。