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

262 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.messaging.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"