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
158 lines
4.8 KiB
Python
Executable File
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)
|