"""queue.py DTO 单元测试。 覆盖 ``EnqueueCmd`` / ``JobId`` / ``JobStatus`` 的字段赋值、默认值、 不可变语义与 ``__post_init__`` 校验逻辑。 """ from __future__ import annotations import dataclasses from datetime import datetime from typing import Any import pytest from yuxi.channels.contract.dtos.queue import ( EnqueueCmd, JobId, JobStatus, ) from yuxi.channels.contract.errors import ValidationError pytestmark = pytest.mark.unit @pytest.mark.unit class TestEnqueueCmd: """入队命令 DTO 测试。""" def test_required_fields_are_assigned(self): # Arrange payload: dict[str, Any] = {"task": "send"} # Act cmd = EnqueueCmd(task_name="send_message", payload=payload) # Assert assert cmd.task_name == "send_message" assert cmd.payload is payload assert cmd.scheduled_at is None assert cmd.idempotency_key is None def test_with_optional_fields(self): # Arrange now = datetime(2026, 1, 1, 12, 0, 0) # Act cmd = EnqueueCmd( task_name="send_message", payload={}, scheduled_at=now, idempotency_key="idem-1", ) # Assert assert cmd.scheduled_at is now assert cmd.idempotency_key == "idem-1" def test_is_frozen(self): # Arrange cmd = EnqueueCmd(task_name="send_message", payload={}) # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): cmd.task_name = "other" # type: ignore[misc] def test_empty_task_name_raises_validation_error(self): # Arrange # Act / Assert with pytest.raises(ValidationError) as exc_info: EnqueueCmd(task_name="", payload={}) assert exc_info.value.field == "task_name" @pytest.mark.unit class TestJobId: """任务 ID DTO 测试。""" def test_value_is_assigned(self): # Arrange # Act job_id = JobId(value="job-1") # Assert assert job_id.value == "job-1" def test_is_frozen(self): # Arrange job_id = JobId(value="job-1") # Act / Assert with pytest.raises(dataclasses.FrozenInstanceError): job_id.value = "other" # type: ignore[misc] @pytest.mark.unit class TestJobStatus: """任务状态枚举测试。""" def test_enum_values_are_correct(self): # Arrange # Act # Assert assert JobStatus.QUEUED == "queued" assert JobStatus.RUNNING == "running" assert JobStatus.COMPLETED == "completed" assert JobStatus.FAILED == "failed" assert JobStatus.CANCELLED == "cancelled" def test_enum_inherits_from_str(self): # Arrange # Act # Assert assert issubclass(JobStatus, str) assert isinstance(JobStatus.QUEUED, str) def test_enum_has_five_members(self): # Arrange # Act members = list(JobStatus) # Assert assert len(members) == 5