我正在尝试使用不同的工具进行模拟,并找出最好的工具。我非常喜欢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)
当我在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
或
>>>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'
答案 0 :(得分:4)
您的第一种方法有正确的想法但不幸的是Python不允许您修改内置对象,如datetime.datetime。 flexmock monkey-patches在运行时调用object和hijacks方法,在这种情况下是不可能的。异常中的错误实际上提到了一个解决方案 - 你可以在你自己的类中包装datetime.datetime然后模拟它。但是如果你真的想要做Mocker在你的例子中所做的事情,只是用一个返回你想要的now()方法创建一个假对象,你可以很容易地做到这一点:
fake_datetime = flexmock(now=lambda: datetime(year=2012, month=12, day=12))
但是,当然,除非你将伪造的日期时间对象注入调用代码,否则常规调用datetime.now()不会被flexmock劫持。
您的第二种方法产生了错误,因为flexmock中的datetime.should_receive('datetime.now')适用于链式方法调用。这意味着它需要一个像datetime.datetime()。now()而不是datetime.datetime.now()这样的调用,所以它最终会抱怨datetime,它现在是一个没有方法的函数now()。