ForcePilot/backend/test/unit/channels/contract/dtos/test_route.py
Kris 3ae9c0bd21 test: 批量修复与新增单元测试用例,清理废弃测试目录
1.  删除了 test/unit/external_systems/framework/ 下的废弃空测试目录
2.  修复多处测试断言逻辑、参数传递与测试数据构造
3.  新增日志级别、缓存令牌、流事件等DTO单元测试
4.  补充路由绑定、会话仓储、outbox仓储的测试覆盖
5.  更新测试用例中的异常类型、参数校验与业务逻辑断言
2026-07-11 21:43:16 +08:00

223 lines
6.7 KiB
Python

"""route.py DTO 单元测试。
覆盖 ``MatchSource`` / ``ConfigMatchSource`` / ``RouteBinding`` /
``MatchTier`` / ``BindingContext`` / ``ConfigFallbackChain`` /
``NestedWhitelistDecision`` / ``RouteBindingRule`` / ``SaveRouteBindingCmd`` /
``UpdateRouteBindingCmd`` / ``RouteBindingFilter`` 的字段赋值、默认值、
不可变语义与 ``__post_init__`` 校验逻辑。
"""
from __future__ import annotations
import dataclasses
from datetime import datetime
import pytest
from yuxi.channels.contract.dtos.channel import ChannelType
from yuxi.channels.contract.dtos.route import (
BindingContext,
ConfigFallbackChain,
ConfigMatchSource,
MatchSource,
MatchTier,
NestedWhitelistDecision,
RouteBinding,
RouteBindingFilter,
RouteBindingRule,
SaveRouteBindingCmd,
UpdateRouteBindingCmd,
)
from yuxi.channels.contract.errors import ValidationError
pytestmark = pytest.mark.unit
@pytest.mark.unit
class TestMatchSource:
"""匹配来源枚举测试。"""
def test_str_values(self):
assert MatchSource.EXPLICIT == "explicit"
assert MatchSource.SESSION == "session"
assert MatchSource.IDENTITY == "identity"
assert MatchSource.DEFAULT == "default"
assert MatchSource.CHAT_TYPE == "chat_type"
@pytest.mark.unit
class TestConfigMatchSource:
"""配置匹配来源枚举测试。"""
def test_str_values(self):
assert ConfigMatchSource.DIRECT == "direct"
assert ConfigMatchSource.PARENT == "parent"
assert ConfigMatchSource.WILDCARD == "wildcard"
assert ConfigMatchSource.CHANNEL_BINDING == "channel_binding"
@pytest.mark.unit
class TestRouteBinding:
"""路由绑定 DTO 测试。"""
def test_fields_are_assigned_with_defaults(self):
# Act
binding = RouteBinding(
channel_account_id="acc-1",
agent_binding="agent-slug",
match_source=MatchSource.EXPLICIT,
)
# Assert
assert binding.channel_session_id is None
assert binding.matched_layer is None
assert binding.config_match_source is None
def test_is_frozen(self):
# Arrange
binding = RouteBinding(
channel_account_id="a1",
agent_binding="slug",
match_source=MatchSource.DEFAULT,
)
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
binding.agent_binding = "other" # type: ignore[misc]
def test_empty_channel_account_id_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
RouteBinding(
channel_account_id="",
agent_binding="slug",
match_source=MatchSource.DEFAULT,
)
assert exc_info.value.field == "channel_account_id"
def test_empty_agent_binding_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
RouteBinding(
channel_account_id="a1",
agent_binding="",
match_source=MatchSource.DEFAULT,
)
assert exc_info.value.field == "agent_binding"
@pytest.mark.unit
class TestMatchTier:
"""匹配层级 DTO 测试。"""
def test_defaults(self):
# Act
tier = MatchTier(name="explicit", priority=0, match_method="exact")
# Assert
assert tier.enabled is True
def test_empty_name_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
MatchTier(name="", priority=0, match_method="exact")
assert exc_info.value.field == "name"
def test_negative_priority_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
MatchTier(name="t", priority=-1, match_method="exact")
assert exc_info.value.field == "priority"
def test_invalid_match_method_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
MatchTier(name="t", priority=0, match_method="invalid") # type: ignore[arg-type]
assert exc_info.value.field == "match_method"
@pytest.mark.unit
class TestBindingContext:
"""绑定上下文 DTO 测试。"""
def test_valid_construction(self):
# Act
ctx = BindingContext(
session_key="session-key",
channel_type=ChannelType("wechat"),
account_id="acc-1",
chat_type="p2p",
peer_id="peer-1",
)
# Assert
assert ctx.conversation_id is None
assert ctx.unified_identity_id is None
def test_empty_session_key_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
BindingContext(
session_key="",
channel_type=ChannelType("wechat"),
account_id="a1",
chat_type="p2p",
peer_id="p1",
)
assert exc_info.value.field == "session_key"
def test_empty_account_id_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
BindingContext(
session_key="sk",
channel_type=ChannelType("wechat"),
account_id="",
chat_type="p2p",
peer_id="p1",
)
assert exc_info.value.field == "account_id"
def test_invalid_chat_type_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
BindingContext(
session_key="sk",
channel_type=ChannelType("wechat"),
account_id="a1",
chat_type="invalid", # type: ignore[arg-type]
peer_id="p1",
)
assert exc_info.value.field == "chat_type"
@pytest.mark.unit
class TestConfigFallbackChain:
"""配置回退链 DTO 测试。"""
def test_fields_are_assigned(self):
# Act
chain = ConfigFallbackChain(
match_key="wechat:*",
match_source=ConfigMatchSource.WILDCARD,
)
# Assert
assert chain.match_value is None
def test_empty_match_key_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
ConfigFallbackChain(
match_key="",
match_source=ConfigMatchSource.DIRECT,
)
assert exc_info.value.field == "match_key"
@pytest.mark.unit
class TestNestedWhitelistDecision:
"""嵌套白名单决策 DTO 测试。"""
def test_defaults(self):
# Act
decision = NestedWhitelistDecision(
outer_configured=True, outer_matched=False
)
# Assert
assert decision.inner_decision is None