2026-01-16 13:15:52 +08:00

493 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using GFramework.Core.Abstractions.state;
using NUnit.Framework;
namespace GFramework.Core.Tests.state;
/// <summary>
/// 测试状态模式实现的功能和行为
/// </summary>
[TestFixture]
public class StateTests
{
/// <summary>
/// 验证状态类是否正确实现了IState接口
/// </summary>
[Test]
public void State_Should_Implement_IState_Interface()
{
var state = new ConcreteStateV2();
Assert.That(state is IState);
}
/// <summary>
/// 验证进入状态时OnEnter方法被正确调用并记录来源状态
/// </summary>
[Test]
public void OnEnter_Should_BeCalled_When_State_Enters()
{
var state = new ConcreteStateV2();
var otherState = new ConcreteStateV3();
state.OnEnter(otherState);
Assert.That(state.EnterCalled, Is.True);
Assert.That(state.EnterFrom, Is.SameAs(otherState));
}
/// <summary>
/// 验证当传入null作为来源状态时的处理情况
/// </summary>
[Test]
public void OnEnter_WithNull_Should_Set_EnterFrom_ToNull()
{
var state = new ConcreteStateV2();
state.OnEnter(null);
Assert.That(state.EnterCalled, Is.True);
Assert.That(state.EnterFrom, Is.Null);
}
/// <summary>
/// 验证退出状态时OnExit方法被正确调用并记录目标状态
/// </summary>
[Test]
public void OnExit_Should_BeCalled_When_State_Exits()
{
var state = new ConcreteStateV2();
var otherState = new ConcreteStateV3();
state.OnExit(otherState);
Assert.That(state.ExitCalled, Is.True);
Assert.That(state.ExitTo, Is.SameAs(otherState));
}
/// <summary>
/// 验证当传入null作为目标状态时的处理情况
/// </summary>
[Test]
public void OnExit_WithNull_Should_Set_ExitTo_ToNull()
{
var state = new ConcreteStateV2();
state.OnExit(null);
Assert.That(state.ExitCalled, Is.True);
Assert.That(state.ExitTo, Is.Null);
}
/// <summary>
/// 验证允许转换时CanTransitionTo方法返回true
/// </summary>
[Test]
public void CanTransitionTo_WithAllowTrue_Should_ReturnTrue()
{
var state = new ConcreteStateV2 { AllowTransitions = true };
var target = new ConcreteStateV3();
var result = state.CanTransitionTo(target);
Assert.That(result, Is.True);
}
/// <summary>
/// 验证不允许转换时CanTransitionTo方法返回false
/// </summary>
[Test]
public void CanTransitionTo_WithAllowFalse_Should_ReturnFalse()
{
var state = new ConcreteStateV2 { AllowTransitions = false };
var target = new ConcreteStateV3();
var result = state.CanTransitionTo(target);
Assert.That(result, Is.False);
}
/// <summary>
/// 验证CanTransitionTo方法正确接收目标状态参数
/// </summary>
[Test]
public void CanTransitionTo_Should_Receive_TargetState()
{
var state = new ConcreteStateV2 { AllowTransitions = true };
var target = new ConcreteStateV3();
IState? receivedTarget = null;
state.CanTransitionToAction = s => receivedTarget = s;
state.CanTransitionTo(target);
Assert.That(receivedTarget, Is.SameAs(target));
}
/// <summary>
/// 验证具有复杂转换规则的状态类功能
/// </summary>
[Test]
public void State_WithComplexTransitionRules_Should_Work()
{
var state1 = new ConditionalStateV2 { AllowedTransitions = new[] { typeof(ConcreteStateV3) } };
var state2 = new ConcreteStateV3();
var state3 = new ConcreteStateV4();
Assert.That(state1.CanTransitionTo(state2), Is.True);
Assert.That(state1.CanTransitionTo(state3), Is.False);
}
/// <summary>
/// 验证多个状态之间的协作功能
/// </summary>
[Test]
public void MultipleStates_Should_WorkTogether()
{
var state1 = new ConcreteStateV2();
var state2 = new ConcreteStateV3();
var state3 = new ConcreteStateV4();
state1.OnEnter(null);
state2.OnEnter(state1);
state3.OnEnter(state2);
Assert.That(state1.EnterCalled, Is.True);
Assert.That(state2.EnterCalled, Is.True);
Assert.That(state3.EnterCalled, Is.True);
Assert.That(state2.EnterFrom, Is.SameAs(state1));
Assert.That(state3.EnterFrom, Is.SameAs(state2));
}
/// <summary>
/// 验证状态对多次转换的跟踪能力
/// </summary>
[Test]
public void State_Should_Track_MultipleTransitions()
{
var state = new TrackingStateV2();
var other = new ConcreteStateV3();
state.OnEnter(other);
state.OnExit(other);
state.OnEnter(other);
state.OnExit(null);
Assert.That(state.EnterCallCount, Is.EqualTo(2));
Assert.That(state.ExitCallCount, Is.EqualTo(2));
}
/// <summary>
/// 验证相同类型状态间的转换处理
/// </summary>
[Test]
public void State_Should_Handle_SameState_Transition()
{
var state1 = new ConcreteStateV2();
var state2 = new ConcreteStateV3();
var state3 = new ConcreteStateV2();
state1.OnEnter(null);
state2.OnEnter(state1);
state3.OnEnter(state2);
Assert.That(state1.EnterFrom, Is.Null);
Assert.That(state2.EnterFrom, Is.SameAs(state1));
Assert.That(state3.EnterFrom, Is.SameAs(state2));
}
}
/// <summary>
/// 具体状态实现类V2版本用于测试状态的基本功能
/// </summary>
public sealed class ConcreteStateV2 : IState
{
/// <summary>
/// 获取或设置是否允许转换
/// </summary>
public bool AllowTransitions { get; set; } = true;
/// <summary>
/// 获取进入状态是否被调用的标志
/// </summary>
public bool EnterCalled { get; private set; }
/// <summary>
/// 获取退出状态是否被调用的标志
/// </summary>
public bool ExitCalled { get; private set; }
/// <summary>
/// 获取进入此状态的来源状态
/// </summary>
public IState? EnterFrom { get; private set; }
/// <summary>
/// 获取从此状态退出的目标状态
/// </summary>
public IState? ExitTo { get; private set; }
/// <summary>
/// 获取或设置转换到目标状态时执行的动作
/// </summary>
public Action<IState>? CanTransitionToAction { get; set; }
/// <summary>
/// 进入当前状态时调用的方法
/// </summary>
/// <param name="from">从哪个状态进入</param>
public void OnEnter(IState? from)
{
EnterCalled = true;
EnterFrom = from;
}
/// <summary>
/// 退出当前状态时调用的方法
/// </summary>
/// <param name="to">退出到哪个状态</param>
public void OnExit(IState? to)
{
ExitCalled = true;
ExitTo = to;
}
/// <summary>
/// 判断是否可以转换到目标状态
/// </summary>
/// <param name="target">目标状态</param>
/// <returns>如果可以转换则返回true否则返回false</returns>
public bool CanTransitionTo(IState target)
{
CanTransitionToAction?.Invoke(target);
return AllowTransitions;
}
}
/// <summary>
/// 具体状态实现类V3版本用于测试状态的基本功能
/// </summary>
public sealed class ConcreteStateV3 : IState
{
/// <summary>
/// 获取进入状态是否被调用的标志
/// </summary>
public bool EnterCalled { get; private set; }
/// <summary>
/// 获取退出状态是否被调用的标志
/// </summary>
public bool ExitCalled { get; private set; }
/// <summary>
/// 获取进入此状态的来源状态
/// </summary>
public IState? EnterFrom { get; private set; }
/// <summary>
/// 获取从此状态退出的目标状态
/// </summary>
public IState? ExitTo { get; private set; }
/// <summary>
/// 进入当前状态时调用的方法
/// </summary>
/// <param name="from">从哪个状态进入</param>
public void OnEnter(IState? from)
{
EnterCalled = true;
EnterFrom = from;
}
/// <summary>
/// 退出当前状态时调用的方法
/// </summary>
/// <param name="to">退出到哪个状态</param>
public void OnExit(IState? to)
{
ExitCalled = true;
ExitTo = to;
}
/// <summary>
/// 判断是否可以转换到目标状态
/// </summary>
/// <param name="target">目标状态</param>
/// <returns>如果可以转换则返回true否则返回false</returns>
public bool CanTransitionTo(IState target)
{
return true;
}
}
/// <summary>
/// 具体状态实现类V4版本用于测试状态的基本功能
/// </summary>
public sealed class ConcreteStateV4 : IState
{
/// <summary>
/// 获取进入状态是否被调用的标志
/// </summary>
public bool EnterCalled { get; private set; }
/// <summary>
/// 获取退出状态是否被调用的标志
/// </summary>
public bool ExitCalled { get; private set; }
/// <summary>
/// 获取进入此状态的来源状态
/// </summary>
public IState? EnterFrom { get; private set; }
/// <summary>
/// 获取从此状态退出的目标状态
/// </summary>
public IState? ExitTo { get; private set; }
/// <summary>
/// 进入当前状态时调用的方法
/// </summary>
/// <param name="from">从哪个状态进入</param>
public void OnEnter(IState? from)
{
EnterCalled = true;
EnterFrom = from;
}
/// <summary>
/// 退出当前状态时调用的方法
/// </summary>
/// <param name="to">退出到哪个状态</param>
public void OnExit(IState? to)
{
ExitCalled = true;
ExitTo = to;
}
/// <summary>
/// 判断是否可以转换到目标状态
/// </summary>
/// <param name="target">目标状态</param>
/// <returns>如果可以转换则返回true否则返回false</returns>
public bool CanTransitionTo(IState target)
{
return true;
}
}
/// <summary>
/// 条件状态实现类V2版本支持基于类型的条件转换规则
/// </summary>
public sealed class ConditionalStateV2 : IState
{
/// <summary>
/// 获取或设置允许转换到的状态类型数组
/// </summary>
public Type[] AllowedTransitions { get; set; } = Array.Empty<Type>();
/// <summary>
/// 获取进入状态是否被调用的标志
/// </summary>
public bool EnterCalled { get; private set; }
/// <summary>
/// 获取退出状态是否被调用的标志
/// </summary>
public bool ExitCalled { get; private set; }
/// <summary>
/// 获取进入此状态的来源状态
/// </summary>
public IState? EnterFrom { get; private set; }
/// <summary>
/// 获取从此状态退出的目标状态
/// </summary>
public IState? ExitTo { get; private set; }
/// <summary>
/// 进入当前状态时调用的方法
/// </summary>
/// <param name="from">从哪个状态进入</param>
public void OnEnter(IState? from)
{
EnterCalled = true;
EnterFrom = from;
}
/// <summary>
/// 退出当前状态时调用的方法
/// </summary>
/// <param name="to">退出到哪个状态</param>
public void OnExit(IState? to)
{
ExitCalled = true;
ExitTo = to;
}
/// <summary>
/// 判断是否可以转换到目标状态
/// </summary>
/// <param name="target">目标状态</param>
/// <returns>如果目标状态类型在允许列表中则返回true否则返回false</returns>
public bool CanTransitionTo(IState target)
{
return AllowedTransitions.Contains(target.GetType());
}
}
/// <summary>
/// 跟踪状态实现类V2版本用于跟踪状态转换次数
/// </summary>
public sealed class TrackingStateV2 : IState
{
/// <summary>
/// 获取进入状态被调用的次数
/// </summary>
public int EnterCallCount { get; private set; }
/// <summary>
/// 获取退出状态被调用的次数
/// </summary>
public int ExitCallCount { get; private set; }
/// <summary>
/// 获取进入此状态的来源状态
/// </summary>
public IState? EnterFrom { get; private set; }
/// <summary>
/// 获取从此状态退出的目标状态
/// </summary>
public IState? ExitTo { get; private set; }
/// <summary>
/// 进入当前状态时调用的方法
/// </summary>
/// <param name="from">从哪个状态进入</param>
public void OnEnter(IState? from)
{
EnterCallCount++;
EnterFrom = from;
}
/// <summary>
/// 退出当前状态时调用的方法
/// </summary>
/// <param name="to">退出到哪个状态</param>
public void OnExit(IState? to)
{
ExitCallCount++;
ExitTo = to;
}
/// <summary>
/// 判断是否可以转换到目标状态
/// </summary>
/// <param name="target">目标状态</param>
/// <returns>总是返回true</returns>
public bool CanTransitionTo(IState target)
{
return true;
}
}