using NUnit.Framework; using BaseGames.Combat.StatusEffects; namespace BaseGames.Tests.EditMode { /// /// StatusEffect 系统单元测试(EditMode,纯 C# 类,无需 MonoBehaviour)。 /// 覆盖:叠加规则、互斥规则、阻断规则、到期检测。 /// [TestFixture] public class StatusEffectTests { // ── 叠加规则 ───────────────────────────────────────────────────────── [Test] public void FireEffect_MaxStacks_IsOne() { var effect = new FireEffect(); Assert.AreEqual(1, effect.MaxStacks); } [Test] public void PoisonEffect_MaxStacks_IsThree() { var effect = new PoisonEffect(); Assert.AreEqual(3, effect.MaxStacks); } [Test] public void PoisonEffect_OnStack_IncreasesStackCount() { var effect = new PoisonEffect(); effect.OnStack(); Assert.AreEqual(2, effect.StackCount); } [Test] public void PoisonEffect_OnStack_ClampsAtMaxStacks() { var effect = new PoisonEffect(); for (int i = 0; i < 10; i++) effect.OnStack(); Assert.AreEqual(effect.MaxStacks, effect.StackCount); } [Test] public void StaggerEffect_MaxStacks_IsOne() { var effect = new StaggerEffect(); Assert.AreEqual(1, effect.MaxStacks); } // ── 互斥规则 ───────────────────────────────────────────────────────── [Test] public void FireEffect_MutualExclusions_ContainsFreeze() { var effect = new FireEffect(); Assert.Contains(StatusEffectType.Freeze, effect.MutualExclusions); } [Test] public void PoisonEffect_MutualExclusions_IsEmpty() { var effect = new PoisonEffect(); Assert.IsEmpty(effect.MutualExclusions); } // ── 阻断规则 ───────────────────────────────────────────────────────── [Test] public void StaggerEffect_BlockedBy_ContainsStun() { var effect = new StaggerEffect(); Assert.Contains(StatusEffectType.Stun, effect.BlockedBy); } [Test] public void FireEffect_BlockedBy_IsEmpty() { var effect = new FireEffect(); Assert.IsEmpty(effect.BlockedBy); } // ── 到期检测 ───────────────────────────────────────────────────────── [Test] public void StatusEffect_IsExpired_AfterDurationDepleted() { var effect = new StaggerEffect(0.5f); effect.OnApply(null); // Owner 可为 null,测试纯时间逻辑 effect.Update(0.3f); Assert.IsFalse(effect.IsExpired); effect.Update(0.3f); // 累计 0.6f > 0.5f Assert.IsTrue(effect.IsExpired); } [Test] public void FireEffect_OnStack_RefreshDuration() { var effectA = new FireEffect(); effectA.OnApply(null); float initialDuration = effectA.Duration; effectA.Update(1.0f); // 消耗部分时间 Assert.Less(effectA.Duration, initialDuration); effectA.OnStack(); // 重叠施加,应刷新持续时间 Assert.AreEqual(initialDuration, effectA.Duration, 0.001f); } // ── 类型标识 ───────────────────────────────────────────────────────── [Test] public void FireEffect_EffectType_IsFire() { Assert.AreEqual(StatusEffectType.Fire, new FireEffect().EffectType); } [Test] public void PoisonEffect_EffectType_IsPoison() { Assert.AreEqual(StatusEffectType.Poison, new PoisonEffect().EffectType); } [Test] public void StaggerEffect_EffectType_IsStagger() { Assert.AreEqual(StatusEffectType.Stagger, new StaggerEffect().EffectType); } // ── 补充测试 ────────────────────────────────────────────────────────── [Test] public void StatusEffect_StackCount_InitialValueIsOne() { var effect = new FireEffect(); Assert.AreEqual(1, effect.StackCount, "新建 Effect 的初始 StackCount 应为 1"); } [Test] public void StatusEffect_Update_RemainingTime_Decreases() { var effect = new StaggerEffect(2.0f); effect.OnApply(null); float initialDuration = effect.Duration; effect.Update(0.5f); Assert.Less(effect.Duration, initialDuration, "Update 后剩余时间应减少"); Assert.IsFalse(effect.IsExpired, "0.5s Update 后 2.0s 效果不应过期"); } [Test] public void StatusEffect_Update_ExactExpiry() { var effect = new StaggerEffect(1.0f); effect.OnApply(null); effect.Update(1.0f); // 恰好耗尽 Assert.IsTrue(effect.IsExpired, "恰好耗尽 duration 后应 IsExpired == true"); } [Test] public void MultipleEffects_IndependentTimers() { var fire = new FireEffect(); var poison = new PoisonEffect(); fire.OnApply(null); poison.OnApply(null); float fireDuration = fire.Duration; float poisonDuration = poison.Duration; fire.Update(0.5f); // poison 未调用 Update,时间不应变化 Assert.AreEqual(poisonDuration, poison.Duration, 0.0001f, "未 Update 的 Effect 持续时间不应减少"); Assert.Less(fire.Duration, fireDuration, "已 Update 的 Effect 持续时间应减少"); } [Test] public void PoisonEffect_OnStack_DoesNotExceedMaxStacks_EdgeCase() { var effect = new PoisonEffect(); // MaxStacks = 3,初始 StackCount = 1,再叠加 2 次达到上限 effect.OnStack(); effect.OnStack(); Assert.AreEqual(3, effect.StackCount); // 再叠加,不应超过 3 effect.OnStack(); effect.OnStack(); Assert.AreEqual(3, effect.StackCount, "StackCount 不应超过 MaxStacks"); } [Test] public void FireEffect_OnApply_ThenExpire_DoesNotThrow() { var effect = new FireEffect(); Assert.DoesNotThrow(() => { effect.OnApply(null); effect.OnExpire(); // 注意:实际 API 为 OnExpire(),文档中误写为 OnRemove() }); } } }