212 lines
7.3 KiB
C#
212 lines
7.3 KiB
C#
using NUnit.Framework;
|
||
using BaseGames.Combat.StatusEffects;
|
||
|
||
namespace BaseGames.Tests.EditMode
|
||
{
|
||
/// <summary>
|
||
/// StatusEffect 系统单元测试(EditMode,纯 C# 类,无需 MonoBehaviour)。
|
||
/// 覆盖:叠加规则、互斥规则、阻断规则、到期检测。
|
||
/// </summary>
|
||
[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()
|
||
});
|
||
}
|
||
}
|
||
}
|