I was having issues while using the code of the accepted answer here.
The code works depending on how I do the import of datetime. Why is that? Is it possible to mock it so it works both ways?
I am using Python 3.4
. The following code illustrates the problem:
import pytest from datetime import datetime mockdate = datetime(2000, 1, 1, 0, 0, 0) @pytest.fixture(autouse=True) def patch_datetime_now(monkeypatch): class mydatetime: @classmethod def now(cls): return mockdate monkeypatch.setattr('datetime.datetime', mydatetime) def test_doesnt_work(): assert datetime.now() == mockdate def test_works(): import datetime assert datetime.datetime.now() == mockdate
The term monkey patch seems to have come from an earlier term, guerrilla patch, which referred to changing code sneakily – and possibly incompatibly with other such patches – at runtime. The word guerrilla, nearly homophonous with gorilla, became monkey, possibly to make the patch sound less intimidating.
Monkey patching is good for testing or mocking out behavior. They can be localized in factory/class decorators/metaclasses where they create a patched new class/object from another object to help with "cross-cutting concerns" in between ALL methods like logging/memoization/caching/database/persistance/unit conversion.
In Python, the term monkey patch refers to dynamic (or run-time) modifications of a class or module. In Python, we can actually change the behavior of code at run-time. We use above module (monk) in below code and change behavior of func() at run-time by assigning different value.
Even if you aren't using mock
framework you should take a look to where to patch chapter. By writing
from datetime import datetime
You are creating a new reference to datetime.datetime
in your test module and call it datetime
. That is the reference that you use in test_doesnt_work()
test.
By writing
monkeypatch.setattr('datetime.datetime', mydatetime)
You are patching datetime
's absolute reference in datetime
module: the one used in test_works()
.
@Michele d'Amico's answer explains why it doesn't work. This is how to make it work if you want to use "from datetime import datetime" instead of just "import datetime"
monkeypatch.setattr(__name__ + '.datetime', mydatetime)
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