Skip to content

Commit 92426c7

Browse files
committed
🏗️ Refactor uvicorn server setup and enhance logging in tests
1 parent 45295c3 commit 92426c7

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

packages/service-library/tests/fastapi/test_cancellation_middleware.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -77,45 +77,49 @@ async def sleep_with_background_task(
7777
def fastapi_app(fastapi_router: APIRouter) -> FastAPI:
7878
app = FastAPI()
7979
app.include_router(fastapi_router)
80-
app.add_middleware(RequestCancellationMiddleware)
80+
81+
app.add_middleware(RequestCancellationMiddleware) # Middleware under test
8182
return app
8283

8384

8485
@pytest.fixture
8586
def uvicorn_server(fastapi_app: FastAPI) -> Iterator[URL]:
86-
random_port = unused_port()
87+
server_port = unused_port()
8788
with log_context(
8889
logging.INFO,
89-
msg=f"with uvicorn server on 127.0.0.1:{random_port}",
90+
msg=f"with uvicorn server on 127.0.0.1:{server_port}",
9091
) as ctx:
92+
9193
config = uvicorn.Config(
9294
fastapi_app,
9395
host="127.0.0.1",
94-
port=random_port,
96+
port=server_port,
9597
log_level="error",
98+
loop="uvloop",
9699
)
97100
server = uvicorn.Server(config)
98101

99102
thread = Thread(target=server.run)
100103
thread.daemon = True
101104
thread.start()
102105

106+
server_url = f"http://127.0.0.1:{server_port}"
107+
103108
@retry(wait=wait_fixed(0.1), stop=stop_after_delay(10), reraise=True)
104109
def wait_for_server_ready() -> None:
105-
with httpx.Client() as client:
106-
response = client.get(f"http://127.0.1:{random_port}/")
107-
assert (
108-
response.is_success
109-
), f"Server did not start successfully: {response.status_code} {response.text}"
110+
response = httpx.get(f"{server_url}/")
111+
assert (
112+
response.is_success
113+
), f"Server did not start successfully: {response.status_code} {response.text}"
110114

111115
wait_for_server_ready()
112116

113117
ctx.logger.info(
114118
"server ready at: %s",
115-
f"http://127.0.0.1:{random_port}",
119+
server_url,
116120
)
117121

118-
yield URL(f"http://127.0.0.1:{random_port}")
122+
yield URL(server_url)
119123

120124
server.should_exit = True
121125
thread.join(timeout=10)
@@ -126,40 +130,49 @@ async def test_server_cancels_when_client_disconnects(
126130
server_done_event: asyncio.Event,
127131
server_cancelled_mock: AsyncMock,
128132
):
133+
# Implementation of RequestCancellationMiddleware is under test here
134+
129135
async with httpx.AsyncClient(base_url=f"{uvicorn_server}") as client:
130-
# check standard call still complete as expected
136+
# 1. check standard call still complete as expected
131137
with log_context(logging.INFO, msg="client calling endpoint"):
132138
response = await client.get("/sleep", params={"sleep_time": 0.1})
139+
133140
assert response.status_code == 200
134141
assert response.json() == {"message": "Slept for 0.1 seconds"}
142+
135143
async with asyncio.timeout(10):
136144
await server_done_event.wait()
137145
server_done_event.clear()
138146

139-
# check slow call get cancelled
147+
# 2. check slow call get cancelled
140148
with log_context(
141149
logging.INFO, msg="client calling endpoint for cancellation"
142150
) as ctx:
143151
with pytest.raises(httpx.ReadTimeout):
144-
response = await client.get(
145-
"/sleep", params={"sleep_time": 10}, timeout=0.1
152+
await client.get(
153+
"/sleep",
154+
params={"sleep_time": 10},
155+
timeout=0.1, # <--- this will enforce the client to disconnect from the server !
146156
)
147157
ctx.logger.info("client disconnected from server")
148158

159+
# request should have been cancelled after the ReadTimoeut!
149160
async with asyncio.timeout(5):
150161
await server_done_event.wait()
151162
server_cancelled_mock.assert_called_once()
152163
server_cancelled_mock.reset_mock()
153164
server_done_event.clear()
154165

166+
# 3. check background tasks get cancelled as well sadly
155167
# NOTE: shows that FastAPI BackgroundTasks get cancelled too!
156-
# check background tasks get cancelled as well sadly
157168
with log_context(logging.INFO, msg="client calling endpoint for cancellation"):
158169
response = await client.get(
159170
"/sleep-with-background-task",
160171
params={"sleep_time": 2},
161172
)
162173
assert response.status_code == 200
174+
175+
# request should have been cancelled after the ReadTimoeut!
163176
async with asyncio.timeout(5):
164177
await server_done_event.wait()
165178
server_cancelled_mock.assert_called_once()

0 commit comments

Comments
 (0)