@@ -241,3 +241,79 @@ async def sub_router_lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
241241
242242 with TestClient (app ) as client :
243243 assert client .app_state == {"router" : True }
244+
245+
246+ @pytest .mark .filterwarnings (
247+ r"ignore:\s*on_event is deprecated, use lifespan event handlers instead.*:DeprecationWarning"
248+ )
249+ def test_router_async_shutdown_handler (state : State ) -> None :
250+ """Test that async on_shutdown event handlers are called correctly, for coverage."""
251+ app = FastAPI ()
252+
253+ @app .get ("/" )
254+ def main () -> dict [str , str ]:
255+ return {"message" : "Hello World" }
256+
257+ @app .on_event ("shutdown" )
258+ async def app_shutdown () -> None :
259+ state .app_shutdown = True
260+
261+ assert state .app_shutdown is False
262+ with TestClient (app ) as client :
263+ assert state .app_shutdown is False
264+ response = client .get ("/" )
265+ assert response .status_code == 200 , response .text
266+ assert state .app_shutdown is True
267+
268+
269+ def test_router_sync_generator_lifespan (state : State ) -> None :
270+ """Test that a sync generator lifespan works via _wrap_gen_lifespan_context."""
271+ from collections .abc import Generator
272+
273+ def lifespan (app : FastAPI ) -> Generator [None , None , None ]:
274+ state .app_startup = True
275+ yield
276+ state .app_shutdown = True
277+
278+ app = FastAPI (lifespan = lifespan ) # type: ignore[arg-type]
279+
280+ @app .get ("/" )
281+ def main () -> dict [str , str ]:
282+ return {"message" : "Hello World" }
283+
284+ assert state .app_startup is False
285+ assert state .app_shutdown is False
286+ with TestClient (app ) as client :
287+ assert state .app_startup is True
288+ assert state .app_shutdown is False
289+ response = client .get ("/" )
290+ assert response .status_code == 200 , response .text
291+ assert response .json () == {"message" : "Hello World" }
292+ assert state .app_startup is True
293+ assert state .app_shutdown is True
294+
295+
296+ def test_router_async_generator_lifespan (state : State ) -> None :
297+ """Test that an async generator lifespan (not wrapped) works."""
298+
299+ async def lifespan (app : FastAPI ) -> AsyncGenerator [None , None ]:
300+ state .app_startup = True
301+ yield
302+ state .app_shutdown = True
303+
304+ app = FastAPI (lifespan = lifespan ) # type: ignore[arg-type]
305+
306+ @app .get ("/" )
307+ def main () -> dict [str , str ]:
308+ return {"message" : "Hello World" }
309+
310+ assert state .app_startup is False
311+ assert state .app_shutdown is False
312+ with TestClient (app ) as client :
313+ assert state .app_startup is True
314+ assert state .app_shutdown is False
315+ response = client .get ("/" )
316+ assert response .status_code == 200 , response .text
317+ assert response .json () == {"message" : "Hello World" }
318+ assert state .app_startup is True
319+ assert state .app_shutdown is True
0 commit comments