Skip to content

Commit d492169

Browse files
committed
test: fix coverage by removing unreachable lifespan and loop body
Remove the unused lifespan context manager (httpx.ASGITransport does not trigger ASGI lifespan events) and the caplog loop assertion (loop body never executes when no errors are logged). The early-return guard rejects unsupported methods before checking _task_group, so the session manager does not need to be running.
1 parent 82d4d14 commit d492169

File tree

1 file changed

+14
-34
lines changed

1 file changed

+14
-34
lines changed

tests/issues/test_1269_head_request_crash.py

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
See: https://github.com/modelcontextprotocol/python-sdk/issues/1269
1010
"""
1111

12-
import logging
13-
from collections.abc import AsyncGenerator
14-
from contextlib import asynccontextmanager
15-
16-
import anyio
1712
import httpx
1813
import pytest
1914
from starlette.applications import Starlette
@@ -24,50 +19,35 @@
2419

2520

2621
def _create_app(*, stateless: bool) -> Starlette:
27-
"""Create a minimal Starlette app backed by a StreamableHTTPSessionManager."""
22+
"""Create a minimal Starlette app backed by a StreamableHTTPSessionManager.
23+
24+
No lifespan is needed because unsupported methods are rejected before
25+
the session manager checks for a running task group.
26+
"""
2827
server = Server("test_head_crash")
2928
session_manager = StreamableHTTPSessionManager(
3029
app=server,
3130
stateless=stateless,
3231
)
3332

34-
@asynccontextmanager
35-
async def lifespan(app: Starlette) -> AsyncGenerator[None, None]:
36-
async with session_manager.run():
37-
yield
38-
3933
return Starlette(
4034
routes=[Mount("/", app=session_manager.handle_request)],
41-
lifespan=lifespan,
4235
)
4336

4437

4538
@pytest.mark.anyio
4639
@pytest.mark.parametrize("stateless", [True, False])
47-
async def test_head_request_returns_405_without_error(
48-
stateless: bool,
49-
caplog: pytest.LogCaptureFixture,
50-
) -> None:
51-
"""HEAD / must return 405 and must not produce ClosedResourceError."""
40+
async def test_head_request_returns_405(stateless: bool) -> None:
41+
"""HEAD / must return 405 without creating a transport."""
5242
app = _create_app(stateless=stateless)
5343

54-
with caplog.at_level(logging.ERROR):
55-
async with httpx.AsyncClient(
56-
transport=httpx.ASGITransport(app=app),
57-
base_url="http://testserver",
58-
timeout=5.0,
59-
) as client:
60-
response = await client.head("/")
61-
assert response.status_code == 405
62-
63-
# Give any lingering background tasks a chance to log errors
64-
await anyio.sleep(0.3)
65-
66-
# Ensure no ClosedResourceError was logged
67-
for record in caplog.records:
68-
msg = record.getMessage()
69-
assert "ClosedResourceError" not in msg, f"ClosedResourceError found in logs: {msg}"
70-
assert "Error in message router" not in msg, f"Message router error found in logs: {msg}"
44+
async with httpx.AsyncClient(
45+
transport=httpx.ASGITransport(app=app),
46+
base_url="http://testserver",
47+
timeout=5.0,
48+
) as client:
49+
response = await client.head("/")
50+
assert response.status_code == 405
7151

7252

7353
@pytest.mark.anyio

0 commit comments

Comments
 (0)