Skip to content

Instantly share code, notes, and snippets.

@nickstenning
Created December 15, 2025 15:56
Show Gist options
  • Select an option

  • Save nickstenning/07d17d06ff46dd81a770cb456d032e75 to your computer and use it in GitHub Desktop.

Select an option

Save nickstenning/07d17d06ff46dd81a770cb456d032e75 to your computer and use it in GitHub Desktop.
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi import FastAPI, APIRouter, Request
from fastapi.testclient import TestClient
def test_lifecycle_subrouters():
@asynccontextmanager
async def app_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
yield {"app": True}
@asynccontextmanager
async def router_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
yield {"router": True}
@asynccontextmanager
async def subrouter_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
yield {"subrouter": True}
subrouter = APIRouter(lifespan=subrouter_lifespan)
router = APIRouter(lifespan=router_lifespan)
router.include_router(subrouter)
app = FastAPI(lifespan=app_lifespan)
app.include_router(router)
@app.get("/state")
def get_state(request: Request):
return request.state._state
with TestClient(app) as client:
assert client.get("/state").json() == {
"app": True,
"router": True,
"subrouter": True,
}
def test_lifecycle_subapps():
@asynccontextmanager
async def app_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
yield {"app": True}
@asynccontextmanager
async def subapp_lifespan(app: FastAPI) -> AsyncGenerator[dict[str, bool], None]:
yield {"subapp": True}
subapp = FastAPI(lifespan=subapp_lifespan)
@subapp.get("/state")
def get_subapp_state(request: Request):
return request.state._state
app = FastAPI(lifespan=app_lifespan)
app.mount("/subapp", subapp)
@app.get("/state")
def get_state(request: Request):
return request.state._state
with TestClient(app) as client:
assert client.get("/state").json() == {
"app": True,
}
# This fails: we get {"app": True} instead.
assert client.get("/subapp/state").json() == {
"app": True,
"subapp": True,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment