Py.test inline object fix

I have a package:

- package/
  - __init__.py
  - cache.py
  - module1.py
  - module2.py
- tests/
  - test_module1.py
  - test_module2.py
  - conftest.py

      

both module1

are module2

imported from cache.py

:

from package.cache import cache

@cache()
def foo():
   ...

      

by default, cache

uses file-based caching specified by dogpile.cache , however when running tests I would like to mock cache

with memory-based caching which is also supported by dogpile.cache .

that's what I'm doing:

# conftest.py

import pytest

@pytest.fixture(autouse=True)
def patch_cache(monkeypatch):
    from dogpile.cache import make_region
    m_cache = make_region().configure('dogpile.cache.memory')
    monkeypatch.setattr('package.cache.cache', m_cache)

      

as you can see, I created a device in which using monkeypatch

to replace cache

withm_cache

however it doesn't work when i run the test with py.test

, they still use the old file based cache. something is wrong?

+3


source to share


2 answers


@cache()

applies when the module is imported because the decorator is called at the top level of the module. If you disable it after importing this module, your patched version will not be applied.



+1


source


I recently had a similar issue with pytest and monkeypatching, which I thought should have been solved with monkeypatch

. I was trying to swap the cache in my flash app for on-board memory so my cached views and other stuff didn't accidentally destroy real app caches.

The problem I found is that, like so unittest.mock.patch

, I had to secure the place where the patch thing is imported and used, such as the site call.

Imagine the following set of modules:

# package1/app1/module1.py

from flask_app import cache
cache.get("SOMEKEY")


# package1/app2/module1.py

from flask_app import cache
cache.get("SOMEKEY")


# package1/app2/module2.py

from package1.app2.module1 import cache
cache.get("SOMEKEY")

      

Now, in pytest, to ensure that all these different versions cache

were monkeypatch

ed, I need a fixture that explicitly sets an attribute on all of them:

# conftest.py
from werkzeug.contrib.cache import SimpleCache

@pytest.fixture(scope="function", autouse=True)
def safe_cache(request, monkeypatch):
    """
    Monkeypatch the cache so it doesn't clobber real keys.

    Clear after every test.
    """
    cache = SimpleCache()
    monkeypatch.setattr('package1.app1.module1.cache', cache)
    monkeypatch.setattr('package1.app2.module1.cache', cache)
    monkeypatch.setattr('package1.app2.module2.cache', cache)    

    def teardown():
        cache.clear()
    request.addfinalizer(teardown)

    return cache

      



This is annoying because every time I write a new module that imports the cache, I also have to render it harmless in the device that the monkey is transferring those caches to.

It works, however.

When I set a breakpoint in one of the modules importing the cache and check what it is using, I see the following:

ipdb> cache
<werkzeug.contrib.cache.SimpleCache object at 0x10d658ac8>

      

My flash app uses Redis cache, so seeing above shows it was successful.

0


source







All Articles