Skip to content

Commit 92521e4

Browse files
📝 Add docstrings to add-middleware-tests
Docstrings generation was requested by @NiveditJain. * #128 (comment) The following files were modified: * `api-server/tests/test_middlewares.py`
1 parent bedae6d commit 92521e4

1 file changed

Lines changed: 95 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import uuid
2+
import pytest
3+
from fastapi import FastAPI, Request
4+
from fastapi.responses import JSONResponse
5+
from fastapi.testclient import TestClient
6+
7+
# Import your middleware classes here
8+
from app.middlewares.request_id_middleware import RequestIdMiddleware
9+
from app.middlewares.unhandled_exceptions_middleware import UnhandledExceptionsMiddleware
10+
11+
# --- Dummy endpoint that returns OK JSON ---
12+
async def ok_endpoint(request: Request):
13+
# When called, respond with JSON {"status": "ok"}
14+
"""
15+
Handle a request and return a JSON response indicating success.
16+
17+
Returns:
18+
JSONResponse: A response with JSON body {"status": "ok"}.
19+
"""
20+
return JSONResponse({"status": "ok"})
21+
22+
# --- Dummy endpoint that raises an exception ---
23+
async def fail_endpoint(request: Request):
24+
# When called, raise a ValueError to simulate an error
25+
"""
26+
Simulates an endpoint that always raises a ValueError to test error handling middleware.
27+
"""
28+
raise ValueError("oops")
29+
30+
@pytest.fixture
31+
def client():
32+
"""
33+
Pytest fixture that provides a TestClient for a FastAPI app configured with custom middlewares and test endpoints.
34+
35+
Returns:
36+
TestClient: A client for simulating HTTP requests to the app with middlewares applied.
37+
"""
38+
app = FastAPI()
39+
40+
# Add middlewares. Order matters! Exceptions should be handled outermost.
41+
app.add_middleware(UnhandledExceptionsMiddleware)
42+
app.add_middleware(RequestIdMiddleware)
43+
44+
# Add routes tied to the dummy endpoints above
45+
app.add_api_route("/ok", ok_endpoint, methods=["GET"])
46+
app.add_api_route("/fail", fail_endpoint, methods=["GET"])
47+
48+
# Return a test client wrapping the ASGI app for test requests
49+
return TestClient(app)
50+
51+
def test_request_id_auto_generated(client):
52+
"""
53+
Test that when no 'x-exosphere-request-id' header is sent, the RequestIdMiddleware
54+
automatically generates a valid UUID and returns it in the response headers.
55+
"""
56+
resp = client.get("/ok") # Make GET request without headers
57+
assert resp.status_code == 200 # Should return HTTP 200 OK
58+
59+
rid = resp.headers["x-exosphere-request-id"] # Get the request ID from headers
60+
uuid.UUID(rid) # Validate that it is a valid UUID (will raise an exception if not)
61+
62+
assert resp.json() == {"status": "ok"} # Response body should be unchanged
63+
64+
def test_request_id_echoed_when_valid(client):
65+
"""
66+
Test that when a valid UUID is provided in header, middleware preserves (echoes) it.
67+
"""
68+
provided = str(uuid.uuid4()) # Generate a valid UUID string
69+
resp = client.get("/ok", headers={"x-exosphere-request-id": provided}) # Send header
70+
71+
assert resp.headers["x-exosphere-request-id"] == provided # Header echoed exactly
72+
73+
def test_request_id_replaced_when_invalid(client):
74+
"""
75+
Test that when an invalid request ID is sent, middleware replaces it with a valid UUID.
76+
"""
77+
resp = client.get("/ok", headers={"x-exosphere-request-id": "invalid-id"}) # Send bad header
78+
79+
new_rid = resp.headers["x-exosphere-request-id"]
80+
assert new_rid != "invalid-id" # Confirm the invalid ID was replaced
81+
uuid.UUID(new_rid) # Confirm replacement is a valid UUID
82+
83+
def test_unhandled_exception_caught(client):
84+
"""
85+
Test that any unhandled exception during request processing is caught by the middleware,
86+
returning a JSON error with HTTP status 500, and still providing a request ID header.
87+
"""
88+
resp = client.get("/fail") # This route raises an exception
89+
90+
assert resp.status_code == 500 # Middleware converts error to HTTP 500 response
91+
92+
body = resp.json()
93+
assert "error" in body or "detail" in body # Error info present in JSON response body
94+
95+
assert "x-exosphere-request-id" in resp.headers # Request ID header is still present

0 commit comments

Comments
 (0)