Skip to content

Commit 3ac881f

Browse files
committed
Test HttpResource.read() instead of excluding it from coverage
The method body had been marked `# pragma: no cover` (widened further once httpx2 moved into the method). Exercise it against an httpx2 MockTransport instead, covering both the response body and the raise_for_status path, and drop the pragma.
1 parent fcaf297 commit 3ac881f

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

‎src/mcp/server/mcpserver/resources/types.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class HttpResource(Resource):
196196
url: str = Field(description="URL to fetch content from")
197197
mime_type: str = Field(default="application/json", description="MIME type of the resource content")
198198

199-
async def read(self) -> str | bytes: # pragma: no cover
199+
async def read(self) -> str | bytes:
200200
"""Read the HTTP content."""
201201
# httpx2 is imported here rather than at module top: this is the only
202202
# resource type that needs the HTTP client stack, and a server that
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from collections.abc import Callable
2+
3+
import httpx2
4+
import pytest
5+
6+
from mcp.server.mcpserver.resources import HttpResource
7+
8+
pytestmark = pytest.mark.anyio
9+
10+
11+
def mock_client_factory(handler: Callable[[httpx2.Request], httpx2.Response]) -> Callable[[], httpx2.AsyncClient]:
12+
"""An `httpx2.AsyncClient` stand-in whose requests are answered by `handler`."""
13+
real_client = httpx2.AsyncClient
14+
15+
def factory() -> httpx2.AsyncClient:
16+
return real_client(transport=httpx2.MockTransport(handler))
17+
18+
return factory
19+
20+
21+
async def test_http_resource_reads_the_response_body_as_text(monkeypatch: pytest.MonkeyPatch):
22+
"""`HttpResource.read()` fetches its URL and returns the response text."""
23+
24+
def handler(request: httpx2.Request) -> httpx2.Response:
25+
return httpx2.Response(200, text=f"body of {request.url}")
26+
27+
monkeypatch.setattr(httpx2, "AsyncClient", mock_client_factory(handler))
28+
resource = HttpResource(uri="resource://remote", url="http://example.test/data")
29+
assert await resource.read() == "body of http://example.test/data"
30+
31+
32+
async def test_http_resource_read_raises_for_error_status(monkeypatch: pytest.MonkeyPatch):
33+
"""A non-2xx response surfaces as `httpx2.HTTPStatusError` rather than being read as content."""
34+
monkeypatch.setattr(httpx2, "AsyncClient", mock_client_factory(lambda request: httpx2.Response(404)))
35+
resource = HttpResource(uri="resource://remote", url="http://example.test/missing")
36+
with pytest.raises(httpx2.HTTPStatusError):
37+
await resource.read()

0 commit comments

Comments
 (0)