I need to patch current datetime in tests. I am using this solution:
def _utcnow(): return datetime.datetime.utcnow() def utcnow(): """A proxy which can be patched in tests. """ # another level of indirection, because some modules import utcnow return _utcnow()
Then in my tests I do something like:
with mock.patch('***.utils._utcnow', return_value=***): ...
But today an idea came to me, that I could make the implementation simpler by patching __call__
of function utcnow
instead of having an additional _utcnow
.
This does not work for me:
from ***.utils import utcnow with mock.patch.object(utcnow, '__call__', return_value=***): ...
How to do this elegantly?
side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.
patch() uses this parameter to pass the mocked object into your test. From there, you can modify the mock or make assertions as necessary. You can execute this test module to ensure it's working as expected: $ python tests.py . -------------------------------------------------------
MagicMock. MagicMock objects provide a simple mocking interface that allows you to set the return value or other behavior of the function or object creation call that you patched. This allows you to fully define the behavior of the call and avoid creating real objects, which can be onerous.
When you patch __call__
of a function, you are setting the __call__
attribute of that instance. Python actually calls the __call__
method defined on the class.
For example:
>>> class A(object): ... def __call__(self): ... print 'a' ... >>> a = A() >>> a() a >>> def b(): print 'b' ... >>> b() b >>> a.__call__ = b >>> a() a >>> a.__call__ = b.__call__ >>> a() a
Assigning anything to a.__call__
is pointless.
However:
>>> A.__call__ = b.__call__ >>> a() b
a()
does not call a.__call__
. It calls type(a).__call__(a)
.
There is a good explanation of why that happens in answer to "Why type(x).__enter__(x)
instead of x.__enter__()
in Python standard contextlib?".
This behaviour is documented in Python documentation on Special method lookup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With