使用Flexmock datetime.datetime.now进行模拟

5 python datetime mocking

我正在尝试使用不同的工具进行模拟,并找出最好的工具.我非常喜欢flexmock的简单性,但我无法弄清楚如何模拟datetime.datetime.now()的行为.

如何在flexmock中模拟以下行为?

>>> from datetime import datetime
>>> mocker = Mocker()
>>> fake_datetime=mocker.replace(datetime)
>>> fake_datetime.now()
<mocker.Mock object at 0x027F1990>
>>> mocker.result(datetime(year=2012, month=12, day=12))
>>> mocker.replay()
>>> datetime.now()
datetime.datetime(2012, 12, 12, 0, 0)
Run Code Online (Sandbox Code Playgroud)

当我在flexmock中尝试相同时:

>>> from datetime import datetime  
>>> fake_datetime = flexmock(datetime)
Traceback (most recent call last):
  File "C:\virtualenvs\webui\lib\site-packages\flexmock.py", line 1194, in flexmock
    return _create_partial_mock(spec, **kwargs)
  File "C:\virtualenvs\webui\lib\site-packages\flexmock.py", line 1013, in 
_create_partial_mock
if (_attach_flexmock_methods(mock, Mock, obj_or_class) and
  File "C:\virtualenvs\webui\lib\site-packages\flexmock.py", line 1030, in
_attach_flexmock_methods
'Python does not allow you to mock builtin objects or modules. '
    'Python does not allow you to mock builtin objects or modules. '
MockBuiltinError: Python does not allow you to mock builtin objects or modules.
Consider wrapping it in a class you can mock instead
Run Code Online (Sandbox Code Playgroud)

要么

>>>flexmock(datetime).should_receive('datetime.now').and_return(datetime.datetime(2012,12,10))
>>> datetime.datetime.now()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'function' object has no attribute 'now'
Run Code Online (Sandbox Code Playgroud)

小智 4

您的第一种方法的想法是正确的,但不幸的是 Python 不允许您修改 datetime.datetime 等内置对象。flexmock 在运行时对对象进行猴子修补并劫持方法调用,这在这种情况下是不可能的。异常中的错误实际上提到了一个解决方案——您可以将 datetime.datetime 包装在您自己的类中,然后模拟它。但如果你真的想做 Mocker 在你的例子中所做的事情,只是用 now() 方法创建一个假对象来返回你想要的东西,你可以很容易地做到这一点:

fake_datetime = flexmock(now=lambda: datetime(year=2012, month=12, day=12))
Run Code Online (Sandbox Code Playgroud)

但是,当然,对 datetime.now() 的常规调用不会被 flexmock 劫持,除非您将伪造的 datetime 对象注入到调用代码中。

您的第二种方法产生了错误,因为 flexmock 中的 datetime.should_receive('datetime.now') 用于链接方法调用。这意味着它期望像 datetime.datetime().now() 这样的调用而不是 datetime.datetime.now() 因此它最终会抱怨 datetime 它期望是一个没有 now() 方法的函数。