Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions database/Validation/TEST008-Error-Handling-Middleware-Testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# TEST008 - Error Handling Middleware Testing

This document records the testing evidence and result for ticket **TEST008**.

## Ticket intent

- Trigger API errors.
- Check response format.
- Confirm consistent error responses.
- Confirm proper status codes.

## Scope

Validated backend error handling behavior implemented in:

- `database/logging_system/request_middleware.py`
- `database/logging_system/exception_handler.py`

Automated tests added in:

- `test/test_t1008_error_handling_middleware.py`

## Test cases implemented

1. **Success path includes request traceability**
- Call `GET /ok`.
- Expect HTTP `200`.
- Expect body: `{"ok": true}`.
- Expect `X-Request-ID` response header is present.

2. **Error path returns consistent format and status**
- Call `GET /explode` (forced runtime exception).
- Expect HTTP `500`.
- Expect body includes:
- `message` = `"Internal server error"`
- `request_id` (non-empty)
- Expect `X-Request-ID` header equals body `request_id`.

## Fix applied during testing

While executing TEST008, one assertion failed because error responses did not include the `X-Request-ID` header.
To align success and error behavior, `global_exception_handler` was updated to set:

- `headers={"X-Request-ID": request_id}`

in the returned `JSONResponse`.

## Execution evidence

Command run from repository root:

```bash
python -m pytest test/test_t1008_error_handling_middleware.py -q
```

Observed result:

```text
.. [100%]
2 passed in 0.30s
```

## Final result

TEST008 acceptance criteria are satisfied by automated tests:

- API errors are triggered and validated.
- Error response format is consistent.
- Proper status codes are returned (`200` success, `500` unhandled error).
- `request_id` tracing is consistent in both payload and response header.
1 change: 1 addition & 0 deletions database/logging_system/exception_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ async def global_exception_handler(request: Request, exc: Exception) -> JSONResp
"message": "Internal server error",
"request_id": request_id,
},
headers={"X-Request-ID": request_id},
)
50 changes: 50 additions & 0 deletions test/test_t1008_error_handling_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import pytest

fastapi = pytest.importorskip("fastapi")
pytest.importorskip("starlette")

from fastapi import FastAPI
from fastapi.testclient import TestClient

from database.logging_system.exception_handler import global_exception_handler
from database.logging_system.request_middleware import RequestLoggingMiddleware


def _build_test_app() -> FastAPI:
app = FastAPI()
app.add_middleware(RequestLoggingMiddleware)
app.add_exception_handler(Exception, global_exception_handler)

@app.get("/ok")
async def ok_route():
return {"ok": True}

@app.get("/explode")
async def explode_route():
raise RuntimeError("TEST008 forced failure")

return app


def test_t1008_success_request_has_request_id_header():
client = TestClient(_build_test_app())

response = client.get("/ok")

assert response.status_code == 200
assert response.json() == {"ok": True}
assert "X-Request-ID" in response.headers
assert response.headers["X-Request-ID"]


def test_t1008_error_response_has_consistent_shape_and_status_code():
client = TestClient(_build_test_app(), raise_server_exceptions=False)

response = client.get("/explode")

assert response.status_code == 500
payload = response.json()
assert payload["message"] == "Internal server error"
assert "request_id" in payload
assert payload["request_id"]
assert response.headers["X-Request-ID"] == payload["request_id"]