22
33import asyncio
44import logging
5+ import threading
56from collections .abc import Iterator
67from threading import Thread
78from unittest .mock import AsyncMock
1920
2021
2122@pytest .fixture
22- def server_done_event () -> asyncio .Event :
23- return asyncio .Event ()
23+ def server_done_event () -> threading .Event :
24+ # This allows communicate an event between the thread where the server is running
25+ # and the test thread. It is used to signal that the server has completed its task
26+ # WARNING: do not user asyncio.Event here as it is not thread-safe!
27+ return threading .Event ()
2428
2529
2630@pytest .fixture
@@ -30,7 +34,7 @@ def server_cancelled_mock() -> AsyncMock:
3034
3135@pytest .fixture
3236def fastapi_router (
33- server_done_event : asyncio .Event , server_cancelled_mock : AsyncMock
37+ server_done_event : threading .Event , server_cancelled_mock : AsyncMock
3438) -> APIRouter :
3539 router = APIRouter ()
3640
@@ -62,7 +66,6 @@ async def _sleep_in_the_back(sleep_time: float) -> None:
6266 await server_cancelled_mock ()
6367 finally :
6468 server_done_event .set ()
65- ctx .logger .info ("current_loop_id=%s" , id (asyncio .get_running_loop ()))
6669
6770 @router .get ("/sleep-with-background-task" )
6871 async def sleep_with_background_task (
@@ -128,7 +131,7 @@ def wait_for_server_ready() -> None:
128131
129132async def test_server_cancels_when_client_disconnects (
130133 uvicorn_server : URL ,
131- server_done_event : asyncio .Event ,
134+ server_done_event : threading .Event ,
132135 server_cancelled_mock : AsyncMock ,
133136):
134137 # Implementation of RequestCancellationMiddleware is under test here
@@ -142,8 +145,7 @@ async def test_server_cancels_when_client_disconnects(
142145 assert response .status_code == 200
143146 assert response .json () == {"message" : "Slept for 0.1 seconds" }
144147
145- async with asyncio .timeout (10 ):
146- await server_done_event .wait ()
148+ server_done_event .wait (10 )
147149 server_done_event .clear ()
148150
149151 # 2. check slow call get cancelled
@@ -158,11 +160,8 @@ async def test_server_cancels_when_client_disconnects(
158160 )
159161 ctx .logger .info ("client disconnected from server" )
160162
161- await asyncio .sleep (0.1 ) # ensure context switches ???
162-
163163 # request should have been cancelled after the ReadTimoeut!
164- async with asyncio .timeout (5 ):
165- await server_done_event .wait ()
164+ server_done_event .wait (5 )
166165 server_cancelled_mock .assert_called_once ()
167166 server_cancelled_mock .reset_mock ()
168167 server_done_event .clear ()
@@ -177,6 +176,5 @@ async def test_server_cancels_when_client_disconnects(
177176 assert response .status_code == 200
178177
179178 # request should have been cancelled after the ReadTimoeut!
180- async with asyncio .timeout (5 ):
181- await server_done_event .wait ()
179+ server_done_event .wait (5 )
182180 server_cancelled_mock .assert_called_once ()
0 commit comments