dotb_ai-platform/tests/test_database_error_mapping.py
hungtran24 2268b6a77a feat: replace tenant auth with app-scoped scoring access
Add app credentials, account-scoped idempotency and per-app terminal notifications. Consolidate the unreleased migration baseline, preserve rule descriptions as AI context, and regenerate provider contracts with regression coverage.
2026-10-02 10:56:58 +07:00

54 lines
1.8 KiB
Python

from types import SimpleNamespace
from uuid import uuid4
import pytest
from fastapi.testclient import TestClient
from sqlalchemy.exc import OperationalError
from ai_platform.bootstrap.app import create_app
from ai_platform.bootstrap.wiring import get_app_credential_use_cases, get_scoring_use_cases
from ai_platform.infrastructure.config.settings import Settings
@pytest.mark.parametrize("boundary", ["auth", "scoring"])
@pytest.mark.parametrize(
"error",
[
OperationalError(
"private-sql", {"credential": "private-key"}, Exception("private-storage-error")
),
ConnectionRefusedError("private-storage-error"),
],
)
def test_database_unavailability_returns_safe_503_on_post_and_get(
valid_run_payload, boundary, error
):
app = create_app(Settings())
async def authenticate(_raw):
return "omni-local"
async def credential_cases():
if boundary == "auth":
raise error
return SimpleNamespace(authenticate=authenticate)
async def scoring_cases():
raise error
app.dependency_overrides[get_app_credential_use_cases] = credential_cases
app.dependency_overrides[get_scoring_use_cases] = scoring_cases
# Dependencies are isolated; this test makes no DB connections or startup mutations.
client = TestClient(app)
headers = {
"Authorization": "Bearer private-key",
"Idempotency-Key": valid_run_payload["request_id"],
}
for response in (
client.post("/v1/lead-scoring/runs", headers=headers, json=valid_run_payload),
client.get(f"/v1/lead-scoring/runs/{uuid4()}", headers=headers),
):
assert response.status_code == 503
assert response.json() == {"detail": "Database unavailable"}
assert "private" not in response.text