Files
Edu/services/ai/tests/test_action_state.py
2026-07-10 18:57:39 +08:00

66 lines
2.6 KiB
Python

"""ActionState 统一响应信封测试."""
from src.ai.models.action_state import ActionState, ErrorDetail
from src.ai.models.chat import ChatData, ChatResponse, Usage
class TestActionState:
"""ActionState 信封测试."""
def test_ok_success(self) -> None:
"""ok() 返回成功响应."""
data = ChatData(content="hello", model="gpt-4o", usage=Usage())
resp = ActionState.ok(data)
assert resp.success is True
assert resp.data is not None
assert resp.data.content == "hello"
assert resp.error is None
def test_error_response(self) -> None:
"""error_response() 返回错误响应."""
resp = ActionState.error_response(
code="AI_LLM_UNAVAILABLE",
message="all providers failed",
details={"tried": ["openai"]},
trace_id="req-123",
)
assert resp.success is False
assert resp.data is None
assert resp.error is not None
assert resp.error.code == "AI_LLM_UNAVAILABLE"
assert resp.error.message == "all providers failed"
assert resp.error.details == {"tried": ["openai"]}
assert resp.error.trace_id == "req-123"
def test_degraded_sets_flags(self) -> None:
"""degraded() 在 data 上设置 degraded + degraded_reason."""
data = ChatData(content="fallback", model="gpt-4o", usage=Usage())
resp = ActionState.degraded(data, "llm unavailable")
assert resp.success is True
assert resp.error is None
assert resp.data is not None
assert resp.data.degraded is True
assert resp.data.degraded_reason == "llm unavailable"
def test_error_detail_alias(self) -> None:
"""ErrorDetail 支持 traceId alias."""
err = ErrorDetail(code="AI_INTERNAL_ERROR", message="boom", trace_id="t-1")
assert err.trace_id == "t-1"
# 序列化使用 alias
dumped = err.model_dump(by_alias=True)
assert dumped["traceId"] == "t-1"
def test_chat_response_inherits_action_state(self) -> None:
"""ChatResponse 继承 ActionState[ChatData]."""
data = ChatData(content="hi", model="m", usage=Usage())
resp = ChatResponse.ok(data)
assert resp.success is True
assert resp.data.content == "hi"
def test_error_response_without_optional_fields(self) -> None:
"""error_response() 可选字段缺省."""
resp = ActionState.error_response("AI_INTERNAL_ERROR", "fail")
assert resp.error is not None
assert resp.error.details is None
assert resp.error.trace_id is None