fastapi-cache icon indicating copy to clipboard operation
fastapi-cache copied to clipboard

Unable to use pytest with cache

Open devanchohan opened this issue 2 years ago • 14 comments

I have a few integration tests than run as part of jenkins job, but I have been unable to get pytests to run and connect to the redis cache. I have tried this but had the same error https://fastapi.tiangolo.com/advanced/testing-events/

Has anyone found a way to test their routes that have a cache?

devanchohan avatar Dec 20 '21 11:12 devanchohan

Anyone faced this issue? I tried the methods outlined in here: https://github.com/tiangolo/fastapi/issues/2003 but I still hit the same issue and tests fail

devanchohan avatar Jan 04 '22 10:01 devanchohan

What problems do you encounter? I finally handled the init error but unfortunately my service function used by the cached endpoint has not been called once. Is there a way to enable/disable the cache for testing or to simulate a cached/uncached request?

sac-cas avatar Feb 15 '22 12:02 sac-cas

I faced the same problem. It fails with "You must call init first!"

sergeytol avatar Apr 07 '22 20:04 sergeytol

add to your conftest.py file

from unittest import mock

mock.patch("fastapi_cache.decorator.cache", lambda *args, **kwargs: lambda f: f).start()

hh-h avatar May 27 '22 12:05 hh-h

you also can try this code below to mock cache.

# conftest.py
from unittest import mock

def mock_cache(*args, **kwargs):
    def wrapper(func):
        @wraps(func)
        async def inner(*args, **kwargs):
            return await func(*args, **kwargs)
        return inner
    return wrapper

mock.patch("fastapi_cache.decorator.cache", mock_cache).start()    

@pytest.fixture(scope="module")
async def client():
    from app.main import app # need to load app module after mock. otherwise, it would fail
    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client

Mark1002 avatar Nov 02 '22 13:11 Mark1002

Hi @Mark1002,

Sorry for being a noop here , but I'm hitting error when trying to use the fixture client. How is client fixture supposed to be used in a test function ?

I have the conftest.py setup as above, then my code below yield error.

import pytest

from app.main import init_app

@pytest.mark.anyio
async def test_api_get_news_details(asyncclient):
    response = await asyncclient.get("/news/34986915")

    assert response.status_code == 200

and here's the error

fixture 'mock_decorator' not found
>       available fixtures: anyio_backend, anyio_backend_name, anyio_backend_options, cache, capfd, capfdbinary, caplog, capsys, capsysbinary, client, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory

What should I do now?

tpthian avatar Mar 08 '23 16:03 tpthian

@tpthian Just put the following code above your imports where you are calling the @cache

mock.patch("fastapi_cache.decorator.cache", lambda *args, **kwargs: lambda f: f).start()

shinyco avatar Mar 17 '23 03:03 shinyco

@tpthian sorry this is my mistake. remove parameter mock_decorator in async def client. i have edit my code snippet above.

Mark1002 avatar Mar 17 '23 03:03 Mark1002

This is a potential area where documentation could provide an example.

mjpieters avatar May 15 '23 11:05 mjpieters

you also can try this code below to mock cache.

# conftest.py
from unittest import mock

def mock_cache(*args, **kwargs):
    def wrapper(func):
        @wraps(func)
        async def inner(*args, **kwargs):
            return await func(*args, **kwargs)
        return inner
    return wrapper

mock.patch("fastapi_cache.decorator.cache", mock_cache).start()    

@pytest.fixture(scope="module")
async def client():
    from app.main import app # need to load app module after mock. otherwise, it would fail
    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client

On my end, none of the suggested solutions worked for me, all failing with 'function' object has no attribute 'start'

CharlesPerrotMinotHCHB avatar Sep 16 '23 06:09 CharlesPerrotMinotHCHB

I am struggling with the same identical problem

dicolasi avatar Oct 20 '23 09:10 dicolasi

ok this works for me.

Create a file called conftest.py within your module and paste this:

from unittest import mock


def mock_cache():
    mock.patch("fastapi_cache.decorator.cache", lambda *args, **kwargs: lambda f: f).start()


def pytest_sessionstart(session):
    mock_cache()

dicolasi avatar Oct 20 '23 09:10 dicolasi

@tpthianПросто поместите следующий код над импортом, где вы вызываете @cache

mock.patch("fastapi_cache.decorator.cache", lambda *args, **kwargs: lambda f: f).start()

thx for the reply it really helped me and solved this problem, but none linter allows to set this code on top😥. On the other hand other solutions don't help me, so we have what we have

Abramov0Alexandr avatar Nov 23 '23 22:11 Abramov0Alexandr