2012-12-26 15 views
5

Sto provando a utilizzare diversi strumenti per deridere e scoprire il migliore. Mi piace molto flexmock per la sua semplicità, ma non riesco a capire come comportarsi da matto di datetime.datetime.now().Mocking con Flexmock datetime.datetime.now

Come simulare il comportamento seguente in 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) 

Quando provo lo stesso in 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 

o

>>>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' 

risposta

4

Il tuo primo approccio ha avuto l'idea giusta, ma purtroppo Python non consente di modificare gli oggetti incorporati come datetime.datetime . flexmock monkey-patch l'oggetto e dirotta le chiamate al metodo in fase di runtime che non è possibile in questo caso. L'errore nell'eccezione in realtà menziona una soluzione: puoi racchiudere datetime.datetime nella tua classe e poi prenderlo in giro. Ma se si vuole veramente fare quello che Mocker ha fatto nel tuo esempio e solo creare un oggetto falso con un ora() metodo che restituisce ciò che si vuole, si può fare abbastanza facilmente:

fake_datetime = flexmock(now=lambda: datetime(year=2012, month=12, day=12)) 

Ma, naturalmente, le chiamate regolari a datetime.now() non verrebbero dirottate da flexmock a meno che non si stesse iniettando il falso oggetto datetime nel codice chiamante.

Il secondo approccio ha generato un errore perché datetime.should_receive ('datetime.now') in flexmock è pensato per chiamate di metodo concatenate. Il che significa che si aspetta una chiamata come datetime.datetime(). Now() piuttosto che datetime.datetime.now() così finisce per lamentarsi di datetime che si aspetta sia una funzione che non ha il metodo now().