using System.Collections.Generic; using System.Reflection; using NUnit.Framework; using UnityEngine; using Colosseum.Combat; using Colosseum.Stats; namespace Colosseum.Tests { /// /// 힐/보호막/버프 스킬의 위협 생성 기능을 검증하는 EditMode 테스트입니다. /// ThreatUtility의 배율 계산과 위협 생성 로직을 검증합니다. /// EnemyBase는 NetworkBehaviour이므로 EditMode에서 인스턴스화할 수 없어 /// 대신 위협 테이블의 동작을 모킹하여 로직을 검증합니다. /// public class SupportThreatTests { // ================================================================ // ResolveThreatMultiplier 테스트 // ================================================================ [Test] public void ResolveThreatMultiplier_NullSource_Returns1() { float multiplier = ThreatUtility.ResolveThreatMultiplier(null); Assert.AreEqual(1f, multiplier, 0.01f, "null 소스는 배율 1.0을 반환해야 합니다."); } [Test] public void ResolveThreatMultiplier_NoModifiers_Returns1() { var go = new GameObject("Test_Caster"); try { float multiplier = ThreatUtility.ResolveThreatMultiplier(go); // ThreatController, PassiveRuntimeController 없음 → 모두 1.0 Assert.AreEqual(1f, multiplier, 0.01f, "배율이 없으면 1.0을 반환해야 합니다."); } finally { Object.DestroyImmediate(go); } } [Test] public void ResolveThreatMultiplier_WithThreatController_ReturnsCorrectValue() { var go = new GameObject("Test_Caster"); try { var threatCtrl = go.AddComponent(); threatCtrl.ApplyThreatMultiplier(2.5f, 999f); float multiplier = ThreatUtility.ResolveThreatMultiplier(go); // 기본 1.0 × 런타임 2.5 = 2.5 Assert.AreEqual(2.5f, multiplier, 0.1f, "ThreatController 배율이 반영되어야 합니다."); } finally { Object.DestroyImmediate(go); } } // ================================================================ // 위협 생성 공식 검증 (로직만) // ================================================================ [Test] public void ThreatFormula_FlatPlusPercent_CalculatesCorrectly() { // 위협 공식: flatThreatAmount + (actualHeal × threatPercent) float flatThreat = 5f; float actualHeal = 80f; float threatPercent = 0.5f; float expected = flatThreat + (actualHeal * threatPercent); // 5 + (80 × 0.5) = 5 + 40 = 45 Assert.AreEqual(45f, expected, 0.01f, "위협 공식이 올바르게 계산되어야 합니다."); } [Test] public void ThreatFormula_ZeroFlat_OnlyPercent() { float flatThreat = 0f; float actualHeal = 100f; float threatPercent = 0.3f; float expected = flatThreat + (actualHeal * threatPercent); // 0 + (100 × 0.3) = 30 Assert.AreEqual(30f, expected, 0.01f, "고정 위협이 0이면 비율만 적용되어야 합니다."); } [Test] public void ThreatFormula_ZeroPercent_OnlyFlat() { float flatThreat = 10f; float actualHeal = 100f; float threatPercent = 0f; float expected = flatThreat + (actualHeal * threatPercent); // 10 + (100 × 0) = 10 Assert.AreEqual(10f, expected, 0.01f, "비율이 0이면 고정 위협만 적용되어야 합니다."); } [Test] public void ThreatFormula_BothZero_NoThreat() { float flatThreat = 0f; float actualHeal = 100f; float threatPercent = 0f; float expected = flatThreat + (actualHeal * threatPercent); Assert.AreEqual(0f, expected, 0.01f, "고정 위협과 비율이 모두 0이면 위협이 없어야 합니다."); } [Test] public void ThreatFormula_FullMultiplierChain_AppliesCorrectly() { // 기본 위협 20, ThreatController 배율 3.0 float baseThreat = 20f; float expectedFinal = baseThreat * 3.0f; // 20 × 3.0 = 60 Assert.AreEqual(60f, expectedFinal, 0.01f, "배율 체인이 올바르게 적용되어야 합니다."); } [Test] public void ThreatFormula_LargeHeal_ScalesCorrectly() { // 대량 힐이 대량 위협을 생성하는지 확인 float flatThreat = 5f; float actualHeal = 500f; float threatPercent = 0.5f; float expected = flatThreat + (actualHeal * threatPercent); // 5 + 250 = 255 Assert.AreEqual(255f, expected, 0.01f, "대량 힐이 비례하여 대량 위협을 생성해야 합니다."); } } }