Python:試圖模擬datetime.date.today()但不工作


5 Answers

另一種選擇是使用https://github.com/spulec/freezegun/

安裝它:

pip install freezegun

並使用它:

from freezegun import freeze_time

@freeze_time("2012-01-01")
def test_something():

    from datetime import datetime
    print(datetime.now()) #  2012-01-01 00:00:00

    from datetime import date
    print(date.today()) #  2012-01-01

它還影響來自其他模塊的方法調用中的其他日期時間調用:

other_module.py:

from datetime import datetime

def other_method():
    print(datetime.now())    

main.py:

from freezegun import freeze_time

@freeze_time("2012-01-01")
def test_something():

    import other_module
    other_module.other_method()

最後:

$ python main.py
# 2012-01-01
Question

誰能告訴我為什麼這不起作用?

>>> import mock
>>> @mock.patch('datetime.date.today')
... def today(cls):
...  return date(2010, 1, 1)
...
>>> from datetime import date
>>> date.today()
datetime.date(2010, 12, 19)

也許有人可以提出更好的方法?







幾天前我面臨同樣的情況,我的解決方案是在模塊中定義一個函數來測試並嘲笑:

def get_date_now():
    return datetime.datetime.now()

今天我發現了FreezeGun ,它似乎FreezeGun地覆蓋了這個案例

from freezegun import freeze_time
import datetime
import unittest


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



要添加到丹尼爾G的解決方案:

from datetime import date

class FakeDate(date):
    "A manipulable date replacement"
    def __new__(cls, *args, **kwargs):
        return date.__new__(date, *args, **kwargs)

這創建了一個類,在實例化時,它將返回一個正常的datetime.date對象,但它也能夠被更改。

@mock.patch('datetime.date', FakeDate)
def test():
    from datetime import date
    FakeDate.today = classmethod(lambda cls: date(2010, 1, 1))
    return date.today()

test() # datetime.date(2010, 1, 1)



對我來說最簡單的方法就是這樣做:

from unittest import patch, Mock

def test():
    datetime_mock = Mock(wraps=datetime)
    datetime_mock.now = Mock(return_value=datetime(1999, 1, 1)
    patch('target_module.datetime', new=datetime_mock).start()



基於Daniel G解決方案,您可以使用以下方法。 這個有利於不使用isinstance(d, datetime.date)打破類型檢查。

import mock

def fixed_today(today):
    from datetime import date

    class FakeDateType(type):
        def __instancecheck__(self, instance):
            return isinstance(instance, date)

    class FakeDate(date):
        __metaclass__ = FakeDateType

        def __new__(cls, *args, **kwargs):
            return date.__new__(date, *args, **kwargs)

        @staticmethod
        def today():
            return today

    return mock.patch("datetime.date", FakeDate)

基本上,我們用我們自己的python子類替換基於C的datetime.date類,它產生原始的datetime.date實例,並且對isinstance()查詢完全按照本地的datetime.date響應。

在測試中將其用作上下文管理器:

with fixed_today(datetime.date(2013, 11, 22)):
    # run the code under test
    # note, that these type checks will not break when patch is active:
    assert isinstance(datetime.date.today(), datetime.date)

類似的方法可以用來模擬datetime.datetime.now()函數。




Related