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

264 lines
7.9 KiB
Python

"""media.py DTO 单元测试。
覆盖 ``MediaType`` 枚举与 ``MediaUploadResult`` / ``MediaDownloadResult`` /
``MediaMetadata`` / ``AttachmentUploadResult`` 的字段赋值、默认值、不可变
语义与 ``__post_init__`` 校验逻辑。
"""
from __future__ import annotations
import dataclasses
from datetime import datetime
import pytest
from yuxi.channels.contract.dtos.media import (
AttachmentUploadResult,
MediaDownloadResult,
MediaMetadata,
MediaType,
MediaUploadResult,
)
from yuxi.channels.contract.errors import ValidationError
pytestmark = pytest.mark.unit
@pytest.mark.unit
class TestMediaType:
"""媒体类型枚举测试。"""
def test_enum_values_are_correct(self):
# Arrange
# Act
# Assert
assert MediaType.IMAGE == "image"
assert MediaType.FILE == "file"
assert MediaType.AUDIO == "audio"
assert MediaType.VIDEO == "video"
def test_enum_inherits_from_str(self):
# Arrange
# Act
# Assert
assert issubclass(MediaType, str)
assert isinstance(MediaType.IMAGE, str)
def test_enum_has_four_members(self):
# Arrange
# Act
members = list(MediaType)
# Assert
assert len(members) == 4
@pytest.mark.unit
class TestMediaUploadResult:
"""媒体上传结果 DTO 测试。"""
def test_required_fields_are_assigned(self):
# Arrange
# Act
result = MediaUploadResult(media_id="img_001")
# Assert
assert result.media_id == "img_001"
assert result.url is None
assert result.expires_at is None
def test_with_all_fields(self):
# Arrange
now = datetime(2026, 1, 1, 12, 0, 0)
# Act
result = MediaUploadResult(
media_id="img_001",
url="https://example.com/img.png",
expires_at=now,
)
# Assert
assert result.url == "https://example.com/img.png"
assert result.expires_at is now
def test_is_frozen(self):
# Arrange
result = MediaUploadResult(media_id="img_001")
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
result.media_id = "other" # type: ignore[misc]
def test_empty_media_id_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
MediaUploadResult(media_id="")
assert exc_info.value.field == "media_id"
@pytest.mark.unit
class TestMediaDownloadResult:
"""媒体下载结果 DTO 测试。"""
def test_fields_are_assigned(self):
# Arrange
content = b"\x89PNG"
# Act
result = MediaDownloadResult(content=content, size=4)
# Assert
assert result.content == content
assert result.size == 4
assert result.filename is None
assert result.mime_type is None
def test_with_optional_fields(self):
# Arrange
# Act
result = MediaDownloadResult(
content=b"data",
size=4,
filename="test.png",
mime_type="image/png",
)
# Assert
assert result.filename == "test.png"
assert result.mime_type == "image/png"
def test_is_frozen(self):
# Arrange
result = MediaDownloadResult(content=b"", size=0)
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
result.size = 100 # type: ignore[misc]
@pytest.mark.unit
class TestMediaMetadata:
"""媒体元数据 DTO 测试。"""
def test_required_fields_are_assigned(self):
# Arrange
# Act
meta = MediaMetadata(
media_id="img_001",
media_type=MediaType.IMAGE,
size=1024,
)
# Assert
assert meta.media_id == "img_001"
assert meta.media_type is MediaType.IMAGE
assert meta.size == 1024
assert meta.mime_type is None
assert meta.created_at is None
def test_with_optional_fields(self):
# Arrange
now = datetime(2026, 1, 1, 12, 0, 0)
# Act
meta = MediaMetadata(
media_id="img_001",
media_type=MediaType.IMAGE,
size=1024,
mime_type="image/png",
created_at=now,
)
# Assert
assert meta.mime_type == "image/png"
assert meta.created_at is now
def test_zero_size_is_valid(self):
# Arrange
# Act
meta = MediaMetadata(media_id="img_001", media_type=MediaType.IMAGE, size=0)
# Assert - size 为 0 是合法的(非负)
assert meta.size == 0
def test_is_frozen(self):
# Arrange
meta = MediaMetadata(media_id="img_001", media_type=MediaType.IMAGE, size=1)
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
meta.media_id = "other" # type: ignore[misc]
def test_empty_media_id_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
MediaMetadata(media_id="", media_type=MediaType.IMAGE, size=1)
assert exc_info.value.field == "media_id"
def test_negative_size_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
MediaMetadata(media_id="img_001", media_type=MediaType.IMAGE, size=-1)
assert exc_info.value.field == "size"
@pytest.mark.unit
class TestAttachmentUploadResult:
"""附件上传结果 DTO 测试。"""
def test_required_fields_are_assigned(self):
# Arrange
# Act
result = AttachmentUploadResult(
attachment_id="att-1",
url="https://example.com/att.png",
mime_type="image/png",
size_bytes=1024,
)
# Assert
assert result.attachment_id == "att-1"
assert result.url == "https://example.com/att.png"
assert result.mime_type == "image/png"
assert result.size_bytes == 1024
assert result.expires_at is None
def test_with_expires_at(self):
# Arrange
now = datetime(2026, 1, 1, 12, 0, 0)
# Act
result = AttachmentUploadResult(
attachment_id="att-1",
url="https://example.com/att.png",
mime_type="image/png",
size_bytes=1024,
expires_at=now,
)
# Assert
assert result.expires_at is now
def test_is_frozen(self):
# Arrange
result = AttachmentUploadResult(
attachment_id="att-1", url="url", mime_type="mt", size_bytes=1
)
# Act / Assert
with pytest.raises(dataclasses.FrozenInstanceError):
result.attachment_id = "other" # type: ignore[misc]
def test_empty_attachment_id_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
AttachmentUploadResult(attachment_id="", url="url", mime_type="mt", size_bytes=1)
assert exc_info.value.field == "attachment_id"
def test_empty_url_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
AttachmentUploadResult(attachment_id="a", url="", mime_type="mt", size_bytes=1)
assert exc_info.value.field == "url"
def test_empty_mime_type_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
AttachmentUploadResult(attachment_id="a", url="url", mime_type="", size_bytes=1)
assert exc_info.value.field == "mime_type"
def test_non_positive_size_bytes_raises_validation_error(self):
# Arrange
# Act / Assert
with pytest.raises(ValidationError) as exc_info:
AttachmentUploadResult(attachment_id="a", url="url", mime_type="mt", size_bytes=0)
assert exc_info.value.field == "size_bytes"