from typing import List, Optional from fastapi import APIRouter, Depends, FastAPI from fastapi.routing import APIRoute from fastapi.testclient import TestClient from pydantic import BaseModel from starlette.routing import BaseRoute deferred_keys = [ "app", "response_fields", "body_field", "response_field", "secure_cloned_response_field", "dependant", "_flat_dependant", "_embed_body_fields", ] def check_if_initialized(route: APIRoute, should_not: bool = False): for key in deferred_keys: if should_not: assert key not in route.__dict__ else: assert key in route.__dict__ def create_test_router( routes: Optional[List[BaseRoute]] = None, defer_init: bool = True ): router = APIRouter(routes=routes or [], defer_init=defer_init) class UserIdBody(BaseModel): user_id: int @router.get("/user_id", dependencies=[Depends(lambda: True)]) async def get_user_id(user_id: int = Depends(lambda: 1)) -> UserIdBody: return {"user_id": user_id} return router def test_route_defers(): app = FastAPI() router = create_test_router(routes=app.router.routes) for route in router.routes: if not isinstance(route, APIRoute): continue check_if_initialized(route, should_not=True) app.router = router client = TestClient(app) response = client.get("/user_id") assert response.status_code == 200 response = client.get("/openapi.json") assert response.status_code == 200 for route in router.routes: if not isinstance(route, APIRoute): continue check_if_initialized(route) def test_route_manual_init(): router = create_test_router() for route in router.routes: check_if_initialized(route, should_not=True) route.init_attributes() check_if_initialized(route) router = create_test_router() router.init_routes() for route in router.routes: check_if_initialized(route) def test_router_defer_init_flag(): route = APIRoute("/test", lambda: {"test": True}, defer_init=False) check_if_initialized(route) deferring_router = create_test_router() router = create_test_router(routes=deferring_router.routes, defer_init=False) for route in router.routes: check_if_initialized(route) def test_root_router_always_initialized(): app = FastAPI() @app.get("/test") async def test_get(): return {"test": 1} router = create_test_router() app.include_router(router) for route in app.router.routes: if not isinstance(route, APIRoute): continue check_if_initialized(route) client = TestClient(app) response = client.get("/test") assert response.status_code == 200