Avoid delayed patching

29 views Asked by At

I'm working on a Python project where I use diskcache.Cache.memoize for caching. I want to write unit tests for my code, and I'm having trouble figuring out how to properly mock diskcache.Cache.memoize using pytest without being delayed in my mocks.

Here's a simplified version of my module:

# my_module.py
import diskcache

cache = diskcache.Cache('/path/to/my/local/cache')

@cache.memoize(expire=3600)
def expensive_function(argument):
    # Expensive calculation here
    return result

I want to write unit tests for expensive_function where I can test the caching behavior on and off via pytest.

I have mocked diskcache.Cache in conftest.py like so:

# conftest.py
import pytest
import unittest.mock
import diskcach


class MockCache:
    def __init__(self, *args, **kwargs):
        pass

    def __call__(self, fun, *args, **kwargs):
        return fun

    def memoize(fun, *args, **kwargs):
        return fun


@pytest.fixture(autouse=True)
def default_mock_memoize(monkeypatch, pytestconfig):
    if not pytestconfig.getoption("--cache"):
        monkeypatch.setattr(diskcache, "Cache", MockCache)


def pytest_addoption(parser):
    parser.addoption(
        "--cache",
        action="store_true",
        default=False,
        help=(
            "Enable caching for tests. Careful: This will disable the test coverage "
            "of the cached code if the return value is in cache."
        ),
    )

This works technically but is too late since it leaves the decorated expensive_function in the hands of the unmocked diskcache.Cache. How can I achieve that diskcache.Cache is mocked before collection?

Thanks in advance for your help!

0

There are 0 answers