Search code examples
pythonpython-3.xmockingpytestmonkeypatching

Why python's monkeypatch doesn't work when importing a class instead of a module?


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

Solution

  • 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().