ForcePilot/backend/test/unit/channels/contract/dtos/test_lifecycle.py
Kris f9f08221fc chore: 整理代码风格与优化细节
本次提交包含多类代码优化:
1. 修复多处单行代码换行格式,统一代码排版
2. 为外部系统模块新增快捷菜单配置
3. 优化前端API请求参数命名一致性
4. 补充媒体下载超限错误码与领域异常类
5. 完善仓储层更新逻辑,支持显式清空字段
6. 优化部分测试用例与工具函数代码结构
7. 为微信插件白名单缓存增加过期时间
2026-07-14 15:13:29 +08:00

138 lines
3.8 KiB
Python

"""lifecycle.py DTO 单元测试。
覆盖 ``LifecycleCmd`` 与 ``LifecycleResult`` 的字段赋值、默认值、不可变
语义与 ``__post_init__`` 校验逻辑。
"""
from __future__ import annotations
import dataclasses
from typing import Any
import pytest
from yuxi.channels.contract.dtos.lifecycle import (
LifecycleCmd,
LifecycleResult,
)
from yuxi.channels.contract.errors import ValidationError
pytestmark = pytest.mark.unit
@pytest.mark.unit
class TestLifecycleCmd:
"""生命周期命令 DTO 测试。"""
def test_fields_are_assigned(self):
# Arrange
# Act
cmd = LifecycleCmd(event="load", plugin_id="plugin-1")
# Assert
assert cmd.event == "load"
assert cmd.plugin_id == "plugin-1"
assert cmd.params is None
def test_with_params(self):
# Arrange
params: dict[str, Any] = {"force": True}
# Act
cmd = LifecycleCmd(event="start", plugin_id="plugin-1", params=params)
# Assert
assert cmd.params is params
@pytest.mark.parametrize(
"event",
["load", "start", "pause", "resume", "stop", "unload", "reload"],
)
def test_valid_events(self, event):
# Arrange
# Act
cmd = LifecycleCmd(event=event, plugin_id="plugin-1") # type: ignore[arg-type]
# Assert
assert cmd.event == event
def test_is_frozen(self):
# Arrange
cmd = LifecycleCmd(event="load", plugin_id="plugin-1")
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
cmd.event = "stop" # type: ignore[misc]
def test_empty_plugin_id_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
LifecycleCmd(event="load", plugin_id="")
assert exc_info.value.field == "plugin_id"
def test_invalid_event_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
LifecycleCmd(event="invalid", plugin_id="plugin-1") # type: ignore[arg-type]
assert exc_info.value.field == "event"
@pytest.mark.unit
class TestLifecycleResult:
"""生命周期结果 DTO 测试。"""
def test_required_fields_are_assigned(self):
# Arrange
# Act
result = LifecycleResult(state="started")
# Assert
assert result.state == "started"
def test_defaults_are_correct(self):
# Arrange
# Act
result = LifecycleResult(state="started")
# Assert
assert result.error is None
assert result.error_code == ""
assert result.trace_id == ""
def test_failed_result_with_error(self):
# Arrange
# Act
result = LifecycleResult(
state="failed",
error="plugin crashed",
error_code="PLUGIN_FAILED",
trace_id="trace-1",
)
# Assert
assert result.state == "failed"
assert result.error == "plugin crashed"
assert result.error_code == "PLUGIN_FAILED"
assert result.trace_id == "trace-1"
@pytest.mark.parametrize(
"state",
[
"discovered",
"resolved",
"loaded",
"initialized",
"started",
"paused",
"stopped",
"unloaded",
"failed",
],
)
def test_valid_states(self, state):
# Arrange
# Act
result = LifecycleResult(state=state) # type: ignore[arg-type]
# Assert
assert result.state == state
def test_is_frozen(self):
# Arrange
result = LifecycleResult(state="started")
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
result.state = "stopped" # type: ignore[misc]