ForcePilot/backend/test/unit/channels/contract/dtos/test_session.py
Kris 08617091dc refactor: 整理项目包结构与导入路径
- 新增多个业务域的__init__.py模块文件,规范包导出结构
- 调整多个DTO文件的导入路径,统一模块组织方式
- 移除测试文件中多余的空行与导入语句
- 优化部分业务模块的包层级划分
2026-07-18 02:04:03 +08:00

204 lines
5.5 KiB
Python

"""session.py DTO 单元测试。
覆盖 ``ChannelSessionId`` / ``PeerId`` / ``ChatType`` / ``SessionOwner`` /
``OwnerTransferCmd`` / ``TemporarySessionPattern`` / ``CloseSessionCmd`` /
``SessionMessageItem`` / ``SessionStatsResult`` / ``BatchCloseSessionsCmd`` /
``BatchCloseResult`` 的字段赋值、默认值、不可变语义与 ``__post_init__``
校验逻辑。
"""
from __future__ import annotations
from datetime import datetime
import pytest
from yuxi.channels.contract.dtos.messaging.common import Operator, OperatorRole
from yuxi.channels.contract.dtos.session.session import (
BatchCloseSessionsCmd,
ChannelSessionId,
ChatType,
CloseSessionCmd,
OwnerTransferCmd,
PeerId,
SessionOwner,
SessionStatsResult,
)
from yuxi.channels.contract.errors import ValidationError
pytestmark = pytest.mark.unit
def _make_operator() -> Operator:
return Operator(user_id="admin-1", role=OperatorRole.ADMIN_USER)
@pytest.mark.unit
class TestChannelSessionId:
"""渠道会话 ID DTO 测试。"""
def test_value_is_assigned(self):
# Act
sid = ChannelSessionId(value="session-001")
# Assert
assert sid.value == "session-001"
@pytest.mark.unit
class TestPeerId:
"""对端 ID DTO 测试。"""
def test_value_is_assigned(self):
# Act
pid = PeerId(value="peer-001")
# Assert
assert pid.value == "peer-001"
@pytest.mark.unit
class TestChatType:
"""会话类型枚举测试。"""
def test_str_values(self):
assert ChatType.P2P == "p2p"
assert ChatType.GROUP == "group"
assert ChatType.KF == "kf"
@pytest.mark.unit
class TestSessionOwner:
"""会话所有者 DTO 测试。"""
def test_fields_are_assigned(self):
# Act
owner = SessionOwner(
conversation_id="conv-1",
owner_peer_id="peer-1",
created_at=datetime(2024, 1, 1),
)
# Assert
assert owner.owner_peer_id == "peer-1"
@pytest.mark.unit
class TestOwnerTransferCmd:
"""所有者转移命令 DTO 测试。"""
def test_valid_construction(self):
# Act
cmd = OwnerTransferCmd(
session_id="sess-1",
new_owner_id="peer-2",
operator=_make_operator(),
)
# Assert
assert cmd.new_owner_id == "peer-2"
def test_empty_session_id_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
OwnerTransferCmd(
session_id="",
new_owner_id="peer-2",
operator=_make_operator(),
)
assert exc_info.value.field == "session_id"
def test_empty_new_owner_id_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
OwnerTransferCmd(
session_id="sess-1",
new_owner_id="",
operator=_make_operator(),
)
assert exc_info.value.field == "new_owner_id"
@pytest.mark.unit
class TestCloseSessionCmd:
"""关闭会话命令 DTO 测试。"""
def test_valid_construction(self):
# Act
cmd = CloseSessionCmd(
session_id="sess-1",
operator=_make_operator(),
)
# Assert
assert cmd.reason is None
def test_empty_session_id_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
CloseSessionCmd(session_id="", operator=_make_operator())
assert exc_info.value.field == "session_id"
@pytest.mark.unit
class TestBatchCloseSessionsCmd:
"""批量关闭会话命令 DTO 测试。"""
def test_valid_with_session_ids(self):
# Act
cmd = BatchCloseSessionsCmd(
operator=_make_operator(),
session_ids=("s1", "s2"),
)
# Assert
assert cmd.max_count == 100
assert cmd.filter is None
def test_valid_with_filter(self):
# Act
cmd = BatchCloseSessionsCmd(
operator=_make_operator(),
filter={"channel_type": "wechat"},
)
# Assert
assert cmd.session_ids == ()
def test_both_empty_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
BatchCloseSessionsCmd(operator=_make_operator())
assert exc_info.value.field == "session_ids"
def test_max_count_below_min_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
BatchCloseSessionsCmd(
operator=_make_operator(),
session_ids=("s1",),
max_count=0,
)
assert exc_info.value.field == "max_count"
def test_max_count_above_max_raises(self):
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
BatchCloseSessionsCmd(
operator=_make_operator(),
session_ids=("s1",),
max_count=1001,
)
assert exc_info.value.field == "max_count"
@pytest.mark.unit
class TestSessionStatsResult:
"""会话统计结果 DTO 测试。"""
def test_fields_are_assigned_with_defaults(self):
# Act
result = SessionStatsResult(
message_count=10,
user_message_count=5,
assistant_message_count=5,
started_at=datetime(2024, 1, 1),
last_activity_at=datetime(2024, 1, 2),
duration_seconds=86400,
)
# Assert
assert result.first_response_seconds is None
assert result.avg_response_seconds is None