1. 删除了 test/unit/external_systems/framework/ 下的废弃空测试目录 2. 修复多处测试断言逻辑、参数传递与测试数据构造 3. 新增日志级别、缓存令牌、流事件等DTO单元测试 4. 补充路由绑定、会话仓储、outbox仓储的测试覆盖 5. 更新测试用例中的异常类型、参数校验与业务逻辑断言
202 lines
5.8 KiB
Python
202 lines
5.8 KiB
Python
"""health.py DTO 单元测试。
|
|
|
|
覆盖 ``WorkerStatus`` / ``RedisStreamStatus`` / ``ConnectionPoolStatus`` /
|
|
``AccountHealthSnapshot`` / ``WorkerHealthSnapshot`` /
|
|
``TransportHealthSnapshot`` / ``DegradedComponentDetail`` / ``HealthQuery`` /
|
|
``HealthSnapshot`` / ``ChannelHealth`` / ``ProbeResult`` /
|
|
``AdapterProbeOutcome`` / ``DiagnosticsExportRequest`` / ``DiagnosticsBundle``
|
|
的字段赋值、默认值、不可变语义与 ``__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.common import Operator, OperatorRole
|
|
from yuxi.channels.contract.dtos.health import (
|
|
AccountHealthSnapshot,
|
|
AdapterProbeOutcome,
|
|
ChannelHealth,
|
|
ConnectionPoolStatus,
|
|
DegradedComponentDetail,
|
|
DiagnosticsBundle,
|
|
DiagnosticsExportRequest,
|
|
HealthQuery,
|
|
HealthSnapshot,
|
|
ProbeResult,
|
|
RedisStreamStatus,
|
|
TransportHealthSnapshot,
|
|
WorkerHealthSnapshot,
|
|
WorkerStatus,
|
|
)
|
|
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 TestWorkerStatus:
|
|
"""队列 Worker 状态值对象测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
status = WorkerStatus(queue_name="default", available=True)
|
|
# Assert
|
|
assert status.queue_depth == 0
|
|
assert status.worker_utilization is None
|
|
assert status.summary == ""
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestRedisStreamStatus:
|
|
"""Redis 流状态值对象测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
status = RedisStreamStatus(available=True, db_size=100)
|
|
# Assert
|
|
assert status.summary == ""
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestConnectionPoolStatus:
|
|
"""数据库连接池状态值对象测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
status = ConnectionPoolStatus(available=True)
|
|
# Assert
|
|
assert status.size == 0
|
|
assert status.reason is None
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestAccountHealthSnapshot:
|
|
"""传输引擎单账号健康状态值对象测试。"""
|
|
|
|
def test_fields_are_assigned(self):
|
|
# Act
|
|
snap = AccountHealthSnapshot(
|
|
channel_type="wechat",
|
|
account_id="acc-1",
|
|
state="running",
|
|
last_activity_at=1000.0,
|
|
backoff_attempt=0,
|
|
consecutive_successes=5,
|
|
)
|
|
# Assert
|
|
assert snap.state == "running"
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestTransportHealthSnapshot:
|
|
"""传输引擎健康状态值对象测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
snap = TransportHealthSnapshot(running=True)
|
|
# Assert
|
|
assert snap.puller is None
|
|
assert snap.stream is None
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestHealthQuery:
|
|
"""健康查询 DTO 测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
query = HealthQuery()
|
|
# Assert
|
|
assert query.channel_filter is None
|
|
assert query.with_probe is False
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestHealthSnapshot:
|
|
"""健康快照 DTO 测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
snap = HealthSnapshot(status="healthy", version="1.0.0")
|
|
# Assert
|
|
assert snap.degraded_components == ()
|
|
assert snap.channels == ()
|
|
assert snap.error_code == ""
|
|
assert snap.trace_id == ""
|
|
assert snap.probed_at is None
|
|
|
|
def test_is_frozen(self):
|
|
# Arrange
|
|
snap = HealthSnapshot(status="healthy", version="1.0.0")
|
|
# Act / Assert
|
|
with pytest.raises(dataclasses.FrozenInstanceError):
|
|
snap.status = "unhealthy" # type: ignore[misc]
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestDiagnosticsExportRequest:
|
|
"""诊断导出请求 DTO 测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
req = DiagnosticsExportRequest(operator=_make_operator())
|
|
# Assert
|
|
assert req.include_audit_logs is True
|
|
assert req.audit_log_count == 100
|
|
|
|
def test_is_frozen(self):
|
|
# Arrange
|
|
req = DiagnosticsExportRequest(operator=_make_operator())
|
|
# Act / Assert
|
|
with pytest.raises(dataclasses.FrozenInstanceError):
|
|
req.audit_log_count = 50 # type: ignore[misc]
|
|
|
|
def test_zero_audit_log_count_raises(self):
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
DiagnosticsExportRequest(operator=_make_operator(), audit_log_count=0)
|
|
assert exc_info.value.field == "audit_log_count"
|
|
|
|
def test_excessive_audit_log_count_raises(self):
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
DiagnosticsExportRequest(operator=_make_operator(), audit_log_count=501)
|
|
assert exc_info.value.field == "audit_log_count"
|
|
|
|
def test_zero_error_log_count_raises(self):
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
DiagnosticsExportRequest(operator=_make_operator(), error_log_count=0)
|
|
assert exc_info.value.field == "error_log_count"
|
|
|
|
def test_excessive_error_log_count_raises(self):
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
DiagnosticsExportRequest(operator=_make_operator(), error_log_count=501)
|
|
assert exc_info.value.field == "error_log_count"
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestDiagnosticsBundle:
|
|
"""诊断包 DTO 测试。"""
|
|
|
|
def test_defaults(self):
|
|
# Act
|
|
bundle = DiagnosticsBundle(
|
|
manifest_snapshot={},
|
|
plugin_states={},
|
|
exported_at=datetime(2024, 1, 1),
|
|
)
|
|
# Assert
|
|
assert bundle.audit_logs == ()
|
|
assert bundle.queue_depth == 0
|
|
assert bundle.worker_status is None
|