Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to run pytests #51

Open
goussous0 opened this issue Jan 25, 2024 · 2 comments
Open

Unable to run pytests #51

goussous0 opened this issue Jan 25, 2024 · 2 comments

Comments

@goussous0
Copy link

According to the github repo README.md I have to use

@asynccontextmanager
async def lifespan(_: FastAPI):
    redis_connection = redis.from_url("redis://localhost:6379", encoding="utf8")
    await FastAPILimiter.init(redis_connection)
    yield
    await FastAPILimiter.close()

or startup event as mentioned on pypi but both approaches seems to result in the same error when trying to run pytests

The following is a basic recreation of the error
config/__init__.py

from fastapi import FastAPI, Depends
import redis.asyncio as redis
from contextlib import asynccontextmanager
from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter

@asynccontextmanager
async def lifespan(_: FastAPI):
    redis_connection = redis.from_url("redis://localhost:6379", encoding="utf8")
    await FastAPILimiter.init(redis_connection)
    yield
    await FastAPILimiter.close()

class App(FastAPI):
    def __init__(self):
        super().__init__(lifespan=lifespan)

        @self.get("/", dependencies=[Depends(RateLimiter(times=2, seconds=5))])
        async def index():
            return {"Hello": "World"}

tests/__init__.py

from config import App
from fastapi.testclient import TestClient

app = App()
client  = TestClient(app)

def test_index():
    resp = client.get("/")
    assert resp.status_code() == 200

the error output

============================= test session starts ==============================
platform linux -- Python 3.11.2, pytest-7.4.4, pluggy-1.4.0
rootdir: /home/test/Desktop/limiter/src
plugins: anyio-4.2.0
collected 1 item

tests/test_example.py F                                                  [100%]

=================================== FAILURES ===================================
__________________________________ test_index __________________________________

    def test_index():
>       resp = client.get("/")

tests/test_example.py:6: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../lib/python3.11/site-packages/starlette/testclient.py:502: in get
    return super().get(
../lib/python3.11/site-packages/httpx/_client.py:1055: in get
    return self.request(
../lib/python3.11/site-packages/starlette/testclient.py:468: in request
    return super().request(
../lib/python3.11/site-packages/httpx/_client.py:828: in request
    return self.send(request, auth=auth, follow_redirects=follow_redirects)
../lib/python3.11/site-packages/httpx/_client.py:915: in send
    response = self._send_handling_auth(
../lib/python3.11/site-packages/httpx/_client.py:943: in _send_handling_auth
    response = self._send_handling_redirects(
../lib/python3.11/site-packages/httpx/_client.py:980: in _send_handling_redirects
    response = self._send_single_request(request)
../lib/python3.11/site-packages/httpx/_client.py:1016: in _send_single_request
    response = transport.handle_request(request)
../lib/python3.11/site-packages/starlette/testclient.py:344: in handle_request
    raise exc
../lib/python3.11/site-packages/starlette/testclient.py:341: in handle_request
    portal.call(self.app, scope, receive, send)
../lib/python3.11/site-packages/anyio/from_thread.py:288: in call
    return cast(T_Retval, self.start_task_soon(func, *args).result())
/usr/lib/python3.11/concurrent/futures/_base.py:449: in result
    return self.__get_result()
/usr/lib/python3.11/concurrent/futures/_base.py:401: in __get_result
    raise self._exception
../lib/python3.11/site-packages/anyio/from_thread.py:217: in _call_func
    retval = await retval_or_awaitable
../lib/python3.11/site-packages/fastapi/applications.py:1054: in __call__
    await super().__call__(scope, receive, send)
../lib/python3.11/site-packages/starlette/applications.py:123: in __call__
    await self.middleware_stack(scope, receive, send)
../lib/python3.11/site-packages/starlette/middleware/errors.py:186: in __call__
    raise exc
../lib/python3.11/site-packages/starlette/middleware/errors.py:164: in __call__
    await self.app(scope, receive, _send)
../lib/python3.11/site-packages/starlette/middleware/exceptions.py:62: in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
../lib/python3.11/site-packages/starlette/_exception_handler.py:64: in wrapped_app
    raise exc
../lib/python3.11/site-packages/starlette/_exception_handler.py:53: in wrapped_app
    await app(scope, receive, sender)
../lib/python3.11/site-packages/starlette/routing.py:762: in __call__
    await self.middleware_stack(scope, receive, send)
../lib/python3.11/site-packages/starlette/routing.py:782: in app
    await route.handle(scope, receive, send)
../lib/python3.11/site-packages/starlette/routing.py:297: in handle
    await self.app(scope, receive, send)
../lib/python3.11/site-packages/starlette/routing.py:77: in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
../lib/python3.11/site-packages/starlette/_exception_handler.py:64: in wrapped_app
    raise exc
../lib/python3.11/site-packages/starlette/_exception_handler.py:53: in wrapped_app
    await app(scope, receive, sender)
../lib/python3.11/site-packages/starlette/routing.py:72: in app
    response = await func(request)
../lib/python3.11/site-packages/fastapi/routing.py:285: in app
    raise e
../lib/python3.11/site-packages/fastapi/routing.py:275: in app
    solved_result = await solve_dependencies(
../lib/python3.11/site-packages/fastapi/dependencies/utils.py:598: in solve_dependencies
    solved = await call(**sub_values)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <fastapi_limiter.depends.RateLimiter object at 0x7f8ae5020810>
request = <starlette.requests.Request object at 0x7f8ae44f0e90>
response = <starlette.responses.Response object at 0x7f8ae44f0e50>

    async def __call__(self, request: Request, response: Response):
        if not FastAPILimiter.redis:
>           raise Exception("You must call FastAPILimiter.init in startup event of fastapi!")
E           Exception: You must call FastAPILimiter.init in startup event of fastapi!

../lib/python3.11/site-packages/fastapi_limiter/depends.py:37: Exception
=========================== short test summary info ============================
FAILED tests/test_example.py::test_index - Exception: You must call FastAPILi...
============================== 1 failed in 0.85s ===============================
@a1d4r
Copy link

a1d4r commented May 5, 2024

I used this dirty hack. Yet it is quite simple and gets the work done.

dependencies = []
if "pytest" not in sys.modules:
    dependencies.append(
        Depends(
            RateLimiter(...)
        )
    )
api_router = APIRouter(prefix="/api/v1", dependencies=dependencies)
# add your routes to `api_router`
app.include_router(api_router)

@BeppeMarnell
Copy link

I used this dirty hack. Yet it is quite simple and gets the work done.

dependencies = []
if "pytest" not in sys.modules:
    dependencies.append(
        Depends(
            RateLimiter(...)
        )
    )
api_router = APIRouter(prefix="/api/v1", dependencies=dependencies)
# add your routes to `api_router`
app.include_router(api_router)

It works good but we need something more robust!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants