关于python:在单元测试时模拟datetime.datetime.now()

Mock datetime.datetime.now() while unit testing

1
2
3
4
5
6
@pytest.mark.parametrize("test_input,expected_output", data)
def test_send_email(test_input, expected_output):
    emails = SendEmails(email_client=MagicMock())
    emails.send_email = MagicMock()
    emails.send_new_email(*test_input)
    emails.send_email.assert_called_with(*expected_output)

我正在寻找模拟datetime.datetime.now(),它在send_new_email方法中调用。但我不确定该怎么做。

我尝试创建一个新的日期时间对象

1
2
 datetime_object = datetime.datetime.strptime('Jun 1 2017  1:33PM',
                                          '%b %d %Y %I:%M%p')

然后重写datetime.datetime.now。

1
datetime.datetime.now = MagicMock(return_value=datetime_object)

但是,我得到了错误

TypeError: can't set attributes of built-in/extension type 'datetime.datetime'

这个问题被标记为python的副本:试图模拟datetime.date.today(),但不起作用

python:试图模拟datetime.date.today(),但不起作用

我已经尝试过这个解决方案,但无法使它工作。由于项目要求,我无法安装Freezegun。

我在测试文件中创建了一个新类

1
2
3
4
5
class NewDate(datetime.date):
@classmethod
def today(cls):
    return cls(2010, 1, 1)
datetime.date = NewDate

但是我不知道如何让sendmails类使用这个。


您可以替换整个类:

1
2
3
4
5
_FAKE_TIME = 0
class _FakeDateTime(datetime.datetime):
    @staticmethod
    def now():
        return _FAKE_TIME

然后使用它:

1
2
_FAKE_TIME = whatever
datetime.datetime = _FakeDateTime

该类需要一些改进,比如比较运算符,以使fakedatetime与datetime具有可比性,但它应该可以工作。