using System.Reflection; using GFramework.Core.Abstractions.state; using GFramework.Core.state; using NUnit.Framework; namespace GFramework.Core.Tests.state; /// /// 测试状态机功能的单元测试类 /// [TestFixture] public class StateMachineTests { /// /// 在每个测试方法执行前初始化状态机实例 /// [SetUp] public void SetUp() { _stateMachine = new StateMachine(); } private StateMachine _stateMachine = null!; /// /// 验证当没有活动状态时,当前状态应为null /// [Test] public void Current_Should_BeNull_When_NoState_Active() { Assert.That(_stateMachine.Current, Is.Null); } /// /// 验证注册状态后,状态会被添加到状态字典中 /// [Test] public void Register_Should_AddState_To_StatesDictionary() { var state = new TestStateV2(); _stateMachine.Register(state); Assert.That(_stateMachine.ContainsState(), Is.True); } /// /// 验证ChangeTo方法能够正确设置当前状态 /// [Test] public void ChangeTo_Should_SetCurrentState() { var state = new TestStateV2(); _stateMachine.Register(state); _stateMachine.ChangeTo(); Assert.That(_stateMachine.Current, Is.SameAs(state)); } /// /// 验证ChangeTo方法会调用OnEnter回调 /// [Test] public void ChangeTo_Should_Invoke_OnEnter() { var state = new TestStateV2(); _stateMachine.Register(state); _stateMachine.ChangeTo(); Assert.That(state.EnterCalled, Is.True); Assert.That(state.EnterFrom, Is.Null); } /// /// 验证当存在当前状态时,切换到新状态会调用原状态的OnExit回调 /// [Test] public void ChangeTo_When_CurrentStateExists_Should_Invoke_OnExit() { var state1 = new TestStateV2(); var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.ChangeTo(); _stateMachine.ChangeTo(); Assert.That(state1.ExitCalled, Is.True); Assert.That(state1.ExitTo, Is.SameAs(state2)); } /// /// 验证当存在当前状态时,切换到新状态会调用新状态的OnEnter回调 /// [Test] public void ChangeTo_When_CurrentStateExists_Should_Invoke_OnEnter() { var state1 = new TestStateV2(); var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.ChangeTo(); _stateMachine.ChangeTo(); Assert.That(state2.EnterCalled, Is.True); Assert.That(state2.EnterFrom, Is.SameAs(state1)); } /// /// 验证切换到相同状态时不应调用回调方法 /// [Test] public void ChangeTo_ToSameState_Should_NotInvoke_Callbacks() { var state = new TestStateV2(); _stateMachine.Register(state); _stateMachine.ChangeTo(); var enterCount = state.EnterCallCount; var exitCount = state.ExitCallCount; _stateMachine.ChangeTo(); Assert.That(state.EnterCallCount, Is.EqualTo(enterCount)); Assert.That(state.ExitCallCount, Is.EqualTo(exitCount)); } /// /// 验证切换到未注册状态时应抛出InvalidOperationException异常 /// [Test] public void ChangeTo_ToUnregisteredState_Should_ThrowInvalidOperationException() { Assert.Throws(() => _stateMachine.ChangeTo()); } /// /// 验证当状态未注册时CanChangeTo方法应返回false /// [Test] public void CanChangeTo_WhenStateNotRegistered_Should_ReturnFalse() { var result = _stateMachine.CanChangeTo(); Assert.That(result, Is.False); } /// /// 验证当状态已注册时CanChangeTo方法应返回true /// [Test] public void CanChangeTo_WhenStateRegistered_Should_ReturnTrue() { var state = new TestStateV2(); _stateMachine.Register(state); var result = _stateMachine.CanChangeTo(); Assert.That(result, Is.True); } /// /// 验证当当前状态拒绝转换时CanChangeTo方法应返回false /// [Test] public void CanChangeTo_WhenCurrentStateDeniesTransition_Should_ReturnFalse() { var state1 = new TestStateV2 { AllowTransition = false }; var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.ChangeTo(); var result = _stateMachine.CanChangeTo(); Assert.That(result, Is.False); } /// /// 验证当当前状态拒绝转换时不应发生状态变化 /// [Test] public void ChangeTo_WhenCurrentStateDeniesTransition_Should_NotChange() { var state1 = new TestStateV2 { AllowTransition = false }; var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.ChangeTo(); var oldState = _stateMachine.Current; var result = _stateMachine.ChangeTo(); Assert.That(result, Is.False); Assert.That(_stateMachine.Current, Is.SameAs(oldState)); Assert.That(_stateMachine.Current, Is.SameAs(state1)); Assert.That(state2.EnterCalled, Is.False); } /// /// 验证注销状态后应从字典中移除该状态 /// [Test] public void Unregister_Should_RemoveState_FromDictionary() { var state = new TestStateV2(); _stateMachine.Register(state); _stateMachine.Unregister(); Assert.That(_stateMachine.ContainsState(), Is.False); } /// /// 验证当活动状态被注销时应调用OnExit并清除当前状态 /// [Test] public void Unregister_WhenStateIsActive_Should_Invoke_OnExit_AndClearCurrent() { var state = new TestStateV2(); _stateMachine.Register(state); _stateMachine.ChangeTo(); _stateMachine.Unregister(); Assert.That(state.ExitCalled, Is.True); Assert.That(state.ExitTo, Is.Null); Assert.That(_stateMachine.Current, Is.Null); } /// /// 验证当非活动状态被注销时不应调用OnExit /// [Test] public void Unregister_WhenStateNotActive_Should_Not_Invoke_OnExit() { var state1 = new TestStateV2(); var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.ChangeTo(); _stateMachine.Unregister(); Assert.That(state1.ExitCalled, Is.False); Assert.That(_stateMachine.Current, Is.SameAs(state1)); } /// /// 验证多次状态转换应正确调用回调方法 /// [Test] public void MultipleStateChanges_Should_Invoke_Callbacks_Correctly() { var state1 = new TestStateV2(); var state2 = new TestStateV3(); var state3 = new TestStateV4(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.Register(state3); _stateMachine.ChangeTo(); _stateMachine.ChangeTo(); _stateMachine.ChangeTo(); Assert.That(state1.EnterCalled, Is.True); Assert.That(state1.ExitCalled, Is.True); Assert.That(state2.EnterCalled, Is.True); Assert.That(state2.ExitCalled, Is.True); Assert.That(state3.EnterCalled, Is.True); Assert.That(state3.ExitCalled, Is.False); } /// /// 验证ChangeTo方法应遵循CanTransitionTo逻辑 /// [Test] public void ChangeTo_Should_Respect_CanTransitionTo_Logic() { var state1 = new TestStateV2(); var state2 = new TestStateV3(); var state3 = new TestStateV4(); _stateMachine.Register(state1); _stateMachine.Register(state2); _stateMachine.Register(state3); _stateMachine.ChangeTo(); _stateMachine.ChangeTo(); Assert.That(state1.EnterCalled, Is.True); Assert.That(state1.ExitCalled, Is.True); Assert.That(state2.EnterCalled, Is.True); } } /// /// 测试状态类V2版本,实现IState接口用于测试 /// public sealed class TestStateV2 : IState { public bool AllowTransition { get; set; } = true; public bool EnterCalled { get; private set; } public bool ExitCalled { get; private set; } public int EnterCallCount { get; private set; } public int ExitCallCount { get; private set; } public IState? EnterFrom { get; private set; } public IState? ExitTo { get; private set; } /// /// 进入状态时的回调方法 /// /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterCallCount++; EnterFrom = from; } /// /// 离开状态时的回调方法 /// /// 离开到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitCallCount++; ExitTo = to; } /// /// 判断是否可以转换到目标状态 /// /// 目标状态 /// 是否允许转换 public bool CanTransitionTo(IState target) { return AllowTransition; } } /// /// 测试状态类V3版本,实现IState接口用于测试 /// public sealed class TestStateV3 : IState { public bool EnterCalled { get; private set; } public bool ExitCalled { get; private set; } public int EnterCallCount { get; private set; } public int ExitCallCount { get; private set; } public IState? EnterFrom { get; private set; } public IState? ExitTo { get; private set; } /// /// 进入状态时的回调方法 /// /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterCallCount++; EnterFrom = from; } /// /// 离开状态时的回调方法 /// /// 离开到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitCallCount++; ExitTo = to; } /// /// 判断是否可以转换到目标状态 /// /// 目标状态 /// 是否允许转换 public bool CanTransitionTo(IState target) { return true; } } /// /// 测试状态类V4版本,实现IState接口用于测试 /// public sealed class TestStateV4 : IState { public bool EnterCalled { get; private set; } public bool ExitCalled { get; private set; } public int EnterCallCount { get; private set; } public int ExitCallCount { get; private set; } public IState? EnterFrom { get; private set; } public IState? ExitTo { get; private set; } /// /// 进入状态时的回调方法 /// /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterCallCount++; EnterFrom = from; } /// /// 离开状态时的回调方法 /// /// 离开到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitCallCount++; ExitTo = to; } /// /// 判断是否可以转换到目标状态 /// /// 目标状态 /// 是否允许转换 public bool CanTransitionTo(IState target) { return true; } } /// /// 状态机扩展方法类 /// public static class StateMachineExtensions { /// /// 检查状态机是否包含指定类型的状态 /// /// 要检查的状态类型 /// 状态机实例 /// 如果包含指定类型的状态则返回true,否则返回false public static bool ContainsState(this StateMachine stateMachine) where T : IState { return stateMachine.GetType().GetField("States", BindingFlags.NonPublic | BindingFlags.Instance)? .GetValue(stateMachine) is Dictionary states && states.ContainsKey(typeof(T)); } }