mirror of
https://github.com/d3vyce/fastapi-toolsets.git
synced 2026-03-01 17:00:48 +01:00
feat: add optional data field in ApiError (#63)
This commit is contained in:
@@ -108,6 +108,24 @@ class TestGenerateErrorResponses:
|
||||
assert example["status"] == "FAIL"
|
||||
assert example["error_code"] == "RES-404"
|
||||
assert example["message"] == "Not Found"
|
||||
assert example["data"] is None
|
||||
|
||||
def test_response_example_with_data(self):
|
||||
"""Generated response includes data when set on ApiError."""
|
||||
|
||||
class ErrorWithData(ApiException):
|
||||
api_error = ApiError(
|
||||
code=400,
|
||||
msg="Bad Request",
|
||||
desc="Invalid input.",
|
||||
err_code="BAD-400",
|
||||
data={"details": "some context"},
|
||||
)
|
||||
|
||||
responses = generate_error_responses(ErrorWithData)
|
||||
example = responses[400]["content"]["application/json"]["example"]
|
||||
|
||||
assert example["data"] == {"details": "some context"}
|
||||
|
||||
|
||||
class TestInitExceptionsHandlers:
|
||||
@@ -137,6 +155,59 @@ class TestInitExceptionsHandlers:
|
||||
assert data["error_code"] == "RES-404"
|
||||
assert data["message"] == "Not Found"
|
||||
|
||||
def test_handles_api_exception_without_data(self):
|
||||
"""ApiException without data returns null data field."""
|
||||
app = FastAPI()
|
||||
init_exceptions_handlers(app)
|
||||
|
||||
@app.get("/error")
|
||||
async def raise_error():
|
||||
raise NotFoundError()
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/error")
|
||||
|
||||
assert response.status_code == 404
|
||||
assert response.json()["data"] is None
|
||||
|
||||
def test_handles_api_exception_with_data(self):
|
||||
"""ApiException with data returns the data payload."""
|
||||
app = FastAPI()
|
||||
init_exceptions_handlers(app)
|
||||
|
||||
class CustomValidationError(ApiException):
|
||||
api_error = ApiError(
|
||||
code=422,
|
||||
msg="Validation Error",
|
||||
desc="1 validation error(s) detected",
|
||||
err_code="CUSTOM-422",
|
||||
data={
|
||||
"errors": [
|
||||
{
|
||||
"field": "email",
|
||||
"message": "invalid format",
|
||||
"type": "value_error",
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
@app.get("/error")
|
||||
async def raise_error():
|
||||
raise CustomValidationError()
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/error")
|
||||
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["data"] == {
|
||||
"errors": [
|
||||
{"field": "email", "message": "invalid format", "type": "value_error"}
|
||||
]
|
||||
}
|
||||
assert data["error_code"] == "CUSTOM-422"
|
||||
|
||||
def test_handles_validation_error(self):
|
||||
"""Handles validation errors with structured response."""
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -46,6 +46,31 @@ class TestApiError:
|
||||
assert error.desc == "The resource was not found."
|
||||
assert error.err_code == "RES-404"
|
||||
|
||||
def test_data_defaults_to_none(self):
|
||||
"""ApiError data field defaults to None."""
|
||||
error = ApiError(
|
||||
code=404,
|
||||
msg="Not Found",
|
||||
desc="The resource was not found.",
|
||||
err_code="RES-404",
|
||||
)
|
||||
assert error.data is None
|
||||
|
||||
def test_create_with_data(self):
|
||||
"""ApiError can be created with a data payload."""
|
||||
error = ApiError(
|
||||
code=422,
|
||||
msg="Validation Error",
|
||||
desc="2 validation error(s) detected",
|
||||
err_code="VAL-422",
|
||||
data={
|
||||
"errors": [{"field": "name", "message": "required", "type": "missing"}]
|
||||
},
|
||||
)
|
||||
assert error.data == {
|
||||
"errors": [{"field": "name", "message": "required", "type": "missing"}]
|
||||
}
|
||||
|
||||
def test_requires_all_fields(self):
|
||||
"""ApiError requires all fields."""
|
||||
with pytest.raises(ValidationError):
|
||||
|
||||
Reference in New Issue
Block a user