"""#1749 generation_preview 配音分配分支测试。 直接测试 create_preview_generation_task 中配音分配逻辑: - count=1: apply_voice_duration_to_plan 被调用 - count>1: ensure_variant_plans / clone + reselect 路径 """ from __future__ import annotations from unittest.mock import MagicMock, call, patch import pytest # ── 辅助 ────────────────────────────────────────────────────────────────────── def _make_user(): mu = MagicMock() mu.user.id = "u1" return mu def _make_task(source_plan_id="src_plan_1"): t = MagicMock() t.id = "task_1" t.source_edit_plan_id = source_plan_id t.extra_meta = {} return t # ═══════════════════════════════════════════════════════════════════════════════ # 直接测 apply_voice_duration_to_plan 的调用入口 # ═══════════════════════════════════════════════════════════════════════════════ class TestPreviewCount1VoiceAllocation: """count=1 预览: clone_plan_for_variant + apply_voice_duration_to_plan。""" def test_clone_then_apply_voice(self): """验证 count=1 且有配音时, clone + apply 被调用。""" from app.services.edit_plan_service import EditPlanService db = MagicMock() svc = EditPlanService.__new__(EditPlanService) svc._clip_repo = MagicMock() svc._clip_repo.session = db svc._plan_repo = MagicMock() svc._generation_task_repo = MagicMock() variant_plan = MagicMock() variant_plan.id = "v_plan_0" svc.clone_plan_for_variant = MagicMock(return_value=variant_plan) svc.apply_voice_duration_to_plan = MagicMock(return_value=variant_plan) # 模拟 count=1 预览配音分配逻辑 source_plan_id = "src_plan_1" voice_durations = [30.0] if source_plan_id: vp = svc.clone_plan_for_variant( source_plan_id, created_by_user_id="u1", name_suffix="预览变体", ) if voice_durations and voice_durations[0] > 0: svc.apply_voice_duration_to_plan(vp.id, voice_durations[0]) svc.clone_plan_for_variant.assert_called_once_with( source_plan_id, created_by_user_id="u1", name_suffix="预览变体", ) svc.apply_voice_duration_to_plan.assert_called_once_with("v_plan_0", 30.0) def test_clone_without_voice_when_duration_zero(self): """voice_durations[0]=0 时不调用 apply。""" from app.services.edit_plan_service import EditPlanService svc = EditPlanService.__new__(EditPlanService) svc._clip_repo = MagicMock() svc._plan_repo = MagicMock() svc._generation_task_repo = MagicMock() vp = MagicMock(id="v_plan_0") svc.clone_plan_for_variant = MagicMock(return_value=vp) svc.apply_voice_duration_to_plan = MagicMock() voice_durations = [0.0] variant_plan = svc.clone_plan_for_variant("src", created_by_user_id="u1", name_suffix="预览变体") if voice_durations and voice_durations[0] > 0: svc.apply_voice_duration_to_plan(variant_plan.id, voice_durations[0]) svc.apply_voice_duration_to_plan.assert_not_called() class TestPreviewCountGt1VoiceAllocation: """count>1 预览: ensure_variant_plans 路径。""" def test_ensure_variant_plans_called(self): """验证 count>1 时 ensure_variant_plans 被正确调用。""" from app.services.edit_plan_service import EditPlanService svc = EditPlanService.__new__(EditPlanService) svc._clip_repo = MagicMock() svc._plan_repo = MagicMock() svc._generation_task_repo = MagicMock() svc.ensure_variant_plans = MagicMock(return_value=["p0", "p1", "p2"]) result = svc.ensure_variant_plans( "src_plan", 3, ["a1", "a2"], created_by_user_id="u1", voice_durations=[30.0, 20.0, 15.0], ) assert result == ["p0", "p1", "p2"] svc.ensure_variant_plans.assert_called_once_with( "src_plan", 3, ["a1", "a2"], created_by_user_id="u1", voice_durations=[30.0, 20.0, 15.0], ) def test_ensure_variant_plans_no_voice(self): """无配音时 voice_durations 全 0 仍可调用。""" from app.services.edit_plan_service import EditPlanService svc = EditPlanService.__new__(EditPlanService) svc._clip_repo = MagicMock() svc._plan_repo = MagicMock() svc._generation_task_repo = MagicMock() svc.ensure_variant_plans = MagicMock(return_value=["p0"]) result = svc.ensure_variant_plans( "src_plan", 1, ["a1"], created_by_user_id="u1", voice_durations=None, ) assert result == ["p0"]