Files
xiaoxia-saas/tests/unit/test_asset_libraries_use_case.py
xiaoxia db85a174b9
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Validate - Code Quality (push) Failing after 1m39s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m11s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 1m4s
CI/CD Pipeline / Unit Tests (push) Successful in 6m4s
CI/CD Pipeline / Integration Tests (push) Successful in 2m20s
CI/CD Pipeline / Frontend Lint (push) Successful in 36s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 1m48s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Failing after 9m40s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m16s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m52s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Has been skipped
test: P3-1 第32波单元测试(bgm_utils/exceptions/asset_libraries) (#807)
2026-07-24 10:24:53 +08:00

158 lines
4.8 KiB
Python
Executable File

"""素材库 UseCase 单元测试."""
from __future__ import annotations
from unittest.mock import MagicMock
import pytest
from packages.application.asset_libraries import (
CreateAssetLibraryCommand,
CreateAssetLibraryUseCase,
ListAssetLibrariesUseCase,
)
from packages.domain import AssetLibrary, AssetLibraryKind
@pytest.fixture
def mock_repo():
repo = MagicMock()
return repo
@pytest.fixture
def sample_library():
lib = AssetLibrary.create(
project_id="proj_456",
name="测试视频库",
kind=AssetLibraryKind.VIDEO,
)
lib.id = "lib_123"
return lib
class TestListAssetLibrariesUseCase:
"""ListAssetLibrariesUseCase 测试"""
def test_list_returns_repo_results(self, mock_repo, sample_library):
"""正常返回 repository 的查询结果"""
mock_repo.find_by_project.return_value = [sample_library]
use_case = ListAssetLibrariesUseCase(mock_repo)
result = use_case.execute("proj_456")
assert len(result) == 1
assert result[0].id == "lib_123"
mock_repo.find_by_project.assert_called_once_with("proj_456")
def test_empty_project_raises_value_error(self, mock_repo):
"""空 project_id 抛出 ValueError"""
use_case = ListAssetLibrariesUseCase(mock_repo)
with pytest.raises(ValueError, match="project_id 不能为空"):
use_case.execute("")
mock_repo.find_by_project.assert_not_called()
def test_whitespace_project_raises_value_error(self, mock_repo):
"""纯空格 project_id 也抛出 ValueError"""
use_case = ListAssetLibrariesUseCase(mock_repo)
with pytest.raises(ValueError, match="project_id 不能为空"):
use_case.execute(" ")
mock_repo.find_by_project.assert_not_called()
def test_project_id_stripped_before_query(self, mock_repo, sample_library):
"""project_id 会被 strip 后再查询"""
mock_repo.find_by_project.return_value = [sample_library]
use_case = ListAssetLibrariesUseCase(mock_repo)
use_case.execute(" proj_456 ")
mock_repo.find_by_project.assert_called_once_with("proj_456")
def test_empty_list(self, mock_repo):
"""项目没有素材库时返回空列表"""
mock_repo.find_by_project.return_value = []
use_case = ListAssetLibrariesUseCase(mock_repo)
result = use_case.execute("proj_456")
assert result == []
class TestCreateAssetLibraryUseCase:
"""CreateAssetLibraryUseCase 测试"""
def test_create_success(self, mock_repo, sample_library):
"""创建成功返回 AssetLibrary"""
mock_repo.create.return_value = sample_library
use_case = CreateAssetLibraryUseCase(mock_repo)
command = CreateAssetLibraryCommand(
project_id="proj_456",
name="新素材库",
kind=AssetLibraryKind.IMAGE,
)
result = use_case.execute(command)
assert result.id == "lib_123"
mock_repo.create.assert_called_once()
# 验证传入 repository 的是一个 AssetLibrary 对象
created = mock_repo.create.call_args[0][0]
assert isinstance(created, AssetLibrary)
assert created.project_id == "proj_456"
assert created.name == "新素材库"
assert created.kind == AssetLibraryKind.IMAGE
def test_create_with_video_kind(self, mock_repo):
"""创建视频类型素材库"""
mock_repo.create.side_effect = lambda x: x
use_case = CreateAssetLibraryUseCase(mock_repo)
command = CreateAssetLibraryCommand(
project_id="proj_1",
name="视频库",
kind=AssetLibraryKind.VIDEO,
)
result = use_case.execute(command)
assert result.kind == AssetLibraryKind.VIDEO
assert result.name == "视频库"
def test_create_with_voice_kind(self, mock_repo):
"""创建音色类型素材库"""
mock_repo.create.side_effect = lambda x: x
use_case = CreateAssetLibraryUseCase(mock_repo)
command = CreateAssetLibraryCommand(
project_id="proj_1",
name="音色库",
kind=AssetLibraryKind.VOICE,
)
result = use_case.execute(command)
assert result.kind == AssetLibraryKind.VOICE
class TestCreateAssetLibraryCommand:
"""CreateAssetLibraryCommand 数据类测试"""
def test_command_fields(self):
"""命令对象字段正确"""
cmd = CreateAssetLibraryCommand(
project_id="proj_1",
name="test",
kind=AssetLibraryKind.VIDEO,
)
assert cmd.project_id == "proj_1"
assert cmd.name == "test"
assert cmd.kind == AssetLibraryKind.VIDEO
def test_command_is_dataclass(self):
"""命令是 dataclass"""
from dataclasses import is_dataclass
assert is_dataclass(CreateAssetLibraryCommand)