feat(backend): 重构 HTTP 错误处理为 RFC7807 标准并优化多个 service
This commit is contained in:
@@ -4,7 +4,7 @@ from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from core.http.errors import ApiProblemError
|
||||
|
||||
from v1.auth.gateway import SupabaseAuthGateway
|
||||
from v1.auth.schemas import (
|
||||
@@ -101,7 +101,7 @@ class TestSupabaseAuthGateway:
|
||||
return_value=SimpleNamespace(session=None, user=None)
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await sut.refresh_session(SessionRefreshRequest(refresh_token="bad"))
|
||||
|
||||
assert exc_info.value.status_code == 401
|
||||
|
||||
@@ -3,8 +3,8 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from core.http.errors import ApiProblemError
|
||||
|
||||
from models.automation_jobs import AutomationJobStatus, ScheduleType
|
||||
from v1.automation_jobs.service import (
|
||||
@@ -203,7 +203,7 @@ class TestCreate:
|
||||
repository.count_user_jobs.return_value = 0
|
||||
repository.create.side_effect = SQLAlchemyError("db down")
|
||||
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
with pytest.raises(ApiProblemError) as exc:
|
||||
await service.create(owner_id, data)
|
||||
|
||||
assert exc.value.status_code == 503
|
||||
@@ -316,7 +316,7 @@ class TestUpdate:
|
||||
repository.get_by_id.return_value = job
|
||||
repository.update.side_effect = SQLAlchemyError("db down")
|
||||
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
with pytest.raises(ApiProblemError) as exc:
|
||||
await service.update(
|
||||
job.id,
|
||||
owner_id,
|
||||
@@ -391,7 +391,7 @@ class TestDelete:
|
||||
repository.get_by_id.return_value = job
|
||||
repository.soft_delete.side_effect = SQLAlchemyError("db down")
|
||||
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
with pytest.raises(ApiProblemError) as exc:
|
||||
await service.delete(job.id, owner_id)
|
||||
|
||||
assert exc.value.status_code == 503
|
||||
|
||||
@@ -6,7 +6,7 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from core.http.errors import ApiProblemError
|
||||
|
||||
from core.auth.models import CurrentUser
|
||||
from models.friendships import Friendship, FriendshipStatus
|
||||
@@ -293,7 +293,7 @@ class TestSendRequest:
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.send_request(
|
||||
FriendRequestCreate(target_user_id=current_user.id, content=None)
|
||||
)
|
||||
@@ -322,7 +322,7 @@ class TestSendRequest:
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.send_request(
|
||||
FriendRequestCreate(target_user_id=USER_B, content=None)
|
||||
)
|
||||
@@ -351,7 +351,7 @@ class TestSendRequest:
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.send_request(
|
||||
FriendRequestCreate(target_user_id=USER_B, content=None)
|
||||
)
|
||||
@@ -411,7 +411,7 @@ class TestAcceptRequest:
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.accept_request(uuid4())
|
||||
|
||||
assert exc_info.value.status_code == 404
|
||||
@@ -447,7 +447,7 @@ class TestAcceptRequest:
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.accept_request(friendship.id)
|
||||
|
||||
assert exc_info.value.status_code == 403
|
||||
@@ -669,7 +669,7 @@ class TestRemoveFriend:
|
||||
current_user=current_user,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.remove_friend(uuid4())
|
||||
|
||||
assert exc_info.value.status_code == 404
|
||||
|
||||
@@ -3,10 +3,10 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from core.auth.models import CurrentUser
|
||||
from core.http.errors import ApiProblemError
|
||||
from models.inbox_messages import (
|
||||
InboxMessage,
|
||||
InboxMessageStatus as InboxMessageModelStatus,
|
||||
@@ -109,11 +109,12 @@ async def test_mark_as_read_raises_404_when_message_missing() -> None:
|
||||
current_user=CurrentUser(id=user_id),
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.mark_as_read(message_id)
|
||||
|
||||
assert exc_info.value.status_code == 404
|
||||
assert exc_info.value.detail == "Inbox message not found"
|
||||
assert exc_info.value.code == "INBOX_MESSAGE_NOT_FOUND"
|
||||
session.commit.assert_not_awaited()
|
||||
|
||||
|
||||
@@ -133,9 +134,10 @@ async def test_mark_as_read_store_error_returns_503() -> None:
|
||||
current_user=CurrentUser(id=user_id),
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.mark_as_read(message_id)
|
||||
|
||||
assert exc_info.value.status_code == 503
|
||||
assert exc_info.value.detail == "Inbox message store unavailable"
|
||||
assert exc_info.value.code == "INBOX_MESSAGE_STORE_UNAVAILABLE"
|
||||
session.rollback.assert_awaited_once()
|
||||
|
||||
@@ -3,7 +3,7 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from core.http.errors import ApiProblemError
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from core.auth.models import CurrentUser
|
||||
@@ -198,7 +198,7 @@ async def test_create_invalid_end_at(
|
||||
inbox_repository=mock_inbox_repository,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.create(request)
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
@@ -234,7 +234,7 @@ async def test_get_by_id_not_found(
|
||||
inbox_repository=mock_inbox_repository,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.get_by_id(uuid4())
|
||||
|
||||
assert exc_info.value.status_code == 404
|
||||
@@ -489,7 +489,7 @@ async def test_list_by_date_range_rolls_back_when_query_fails_after_archive(
|
||||
inbox_repository=mock_inbox_repository,
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
with pytest.raises(ApiProblemError) as exc_info:
|
||||
await service.list_by_date_range(
|
||||
request=ScheduleItemListRequest(
|
||||
start_at=datetime(2026, 2, 1, 0, 0, tzinfo=timezone.utc),
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
from uuid import UUID
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from core.http.errors import ApiProblemError
|
||||
|
||||
from core.auth.jwt_verifier import TokenValidationError
|
||||
import v1.users.dependencies as deps
|
||||
@@ -49,7 +49,7 @@ async def test_get_current_user_raises_401_when_fallback_fails(monkeypatch) -> N
|
||||
|
||||
monkeypatch.setattr(deps, "_verify_user_with_supabase", _fallback)
|
||||
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
with pytest.raises(ApiProblemError) as exc:
|
||||
await deps.get_current_user(authorization="Bearer invalid-token")
|
||||
|
||||
assert exc.value.status_code == 401
|
||||
|
||||
Reference in New Issue
Block a user