Open devanchohan opened 2 years ago
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
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?
I faced the same problem. It fails with "You must call init first!"
add to your conftest.py file
from unittest import mock
mock.patch("fastapi_cache.decorator.cache", lambda *args, **kwargs: lambda f: f).start()
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
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 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()
@tpthian sorry this is my mistake. remove parameter mock_decorator
in async def client
. i have edit my code snippet above.
This is a potential area where documentation could provide an example.
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'
I am struggling with the same identical problem
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()
@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
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
this worked for me. thank you @Mark1002. i was stuck on this for sooooo long - here's the top of my conftest.py if it helps anyone else in the future:
from functools import wraps
from unittest import mock
import pytest
from fastapi.testclient import TestClient
# We need to disable the @cache decorator during testing
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()
# FastAPI "app" instance needs to be imported after this mocking
from ..main import app
@pytest.fixture(scope="module")
def client():
with TestClient(app) as test_client:
yield test_client
I faced the same problem. It fails with "You must call init first!"
The error occurs because FastAPICache has not been initialized before use. Here are steps you can take to solve this problem:
Initialize FastAPICache in your main application file (usually main.py). You should do this after creating an instance of FastAPI. For tests, you will need to create a dummy cache backend.
This solution worked for me: 1.In your main application file (e.g. app/main.py):
@app.on_event("startup"). async def startup(): FastAPICache.init(InMemoryBackend())
2.In the conftest.py file, added the following:
@pytest.fixture(autouse=True, scope="function") def fastapi_cache(): FastAPICache.init(InMemoryBackend())
@pytest.mark.asyncio async def test_add_data(ac: AsyncClient, fastapi_cache):
seems to be the cleanest solution!
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?