Skip to content

Commit fd93213

Browse files
authored
TEST008 - Error Handling Middleware Testing (#88)
1 parent c75a70d commit fd93213

3 files changed

Lines changed: 121 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# TEST008 - Error Handling Middleware Testing
2+
3+
This document records the testing evidence and result for ticket **TEST008**.
4+
5+
## Ticket intent
6+
7+
- Trigger API errors.
8+
- Check response format.
9+
- Confirm consistent error responses.
10+
- Confirm proper status codes.
11+
12+
## Scope
13+
14+
Validated backend error handling behavior implemented in:
15+
16+
- `database/logging_system/request_middleware.py`
17+
- `database/logging_system/exception_handler.py`
18+
19+
Automated tests added in:
20+
21+
- `test/test_t1008_error_handling_middleware.py`
22+
23+
## Test cases implemented
24+
25+
1. **Success path includes request traceability**
26+
- Call `GET /ok`.
27+
- Expect HTTP `200`.
28+
- Expect body: `{"ok": true}`.
29+
- Expect `X-Request-ID` response header is present.
30+
31+
2. **Error path returns consistent format and status**
32+
- Call `GET /explode` (forced runtime exception).
33+
- Expect HTTP `500`.
34+
- Expect body includes:
35+
- `message` = `"Internal server error"`
36+
- `request_id` (non-empty)
37+
- Expect `X-Request-ID` header equals body `request_id`.
38+
39+
## Fix applied during testing
40+
41+
While executing TEST008, one assertion failed because error responses did not include the `X-Request-ID` header.
42+
To align success and error behavior, `global_exception_handler` was updated to set:
43+
44+
- `headers={"X-Request-ID": request_id}`
45+
46+
in the returned `JSONResponse`.
47+
48+
## Execution evidence
49+
50+
Command run from repository root:
51+
52+
```bash
53+
python -m pytest test/test_t1008_error_handling_middleware.py -q
54+
```
55+
56+
Observed result:
57+
58+
```text
59+
.. [100%]
60+
2 passed in 0.30s
61+
```
62+
63+
## Final result
64+
65+
TEST008 acceptance criteria are satisfied by automated tests:
66+
67+
- API errors are triggered and validated.
68+
- Error response format is consistent.
69+
- Proper status codes are returned (`200` success, `500` unhandled error).
70+
- `request_id` tracing is consistent in both payload and response header.

database/logging_system/exception_handler.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ async def global_exception_handler(request: Request, exc: Exception) -> JSONResp
3838
"message": "Internal server error",
3939
"request_id": request_id,
4040
},
41+
headers={"X-Request-ID": request_id},
4142
)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import pytest
2+
3+
fastapi = pytest.importorskip("fastapi")
4+
pytest.importorskip("starlette")
5+
6+
from fastapi import FastAPI
7+
from fastapi.testclient import TestClient
8+
9+
from database.logging_system.exception_handler import global_exception_handler
10+
from database.logging_system.request_middleware import RequestLoggingMiddleware
11+
12+
13+
def _build_test_app() -> FastAPI:
14+
app = FastAPI()
15+
app.add_middleware(RequestLoggingMiddleware)
16+
app.add_exception_handler(Exception, global_exception_handler)
17+
18+
@app.get("/ok")
19+
async def ok_route():
20+
return {"ok": True}
21+
22+
@app.get("/explode")
23+
async def explode_route():
24+
raise RuntimeError("TEST008 forced failure")
25+
26+
return app
27+
28+
29+
def test_t1008_success_request_has_request_id_header():
30+
client = TestClient(_build_test_app())
31+
32+
response = client.get("/ok")
33+
34+
assert response.status_code == 200
35+
assert response.json() == {"ok": True}
36+
assert "X-Request-ID" in response.headers
37+
assert response.headers["X-Request-ID"]
38+
39+
40+
def test_t1008_error_response_has_consistent_shape_and_status_code():
41+
client = TestClient(_build_test_app(), raise_server_exceptions=False)
42+
43+
response = client.get("/explode")
44+
45+
assert response.status_code == 500
46+
payload = response.json()
47+
assert payload["message"] == "Internal server error"
48+
assert "request_id" in payload
49+
assert payload["request_id"]
50+
assert response.headers["X-Request-ID"] == payload["request_id"]

0 commit comments

Comments
 (0)