GFramework/GFramework.Core.Tests/state/StateMachineSystemTests.cs
GeWuYou c8be4b317d refactor(core): 将命令和查询总线重构为执行器模式
- 将 CommandBus 重命名为 CommandExecutor 并更新相关接口
- 将 QueryBus 重命名为 QueryExecutor 并更新相关接口
- 将 AsyncQueryBus 重命名为 AsyncQueryExecutor 并更新相关接口
- 更新 ArchitectureContext 中的服务引用和错误消息
- 修改 ArchitectureServices 中的私有字段和公共属性名称
- 更新所有测试文件中的实例变量和服务引用
- 修改测试类名称以匹配新的执行器命名
- 更新状态机系统测试中的容器注册项
2026-02-05 12:46:44 +08:00

373 lines
11 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 System.Reflection;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.Abstractions.state;
using GFramework.Core.Abstractions.system;
using GFramework.Core.architecture;
using GFramework.Core.command;
using GFramework.Core.environment;
using GFramework.Core.events;
using GFramework.Core.ioc;
using GFramework.Core.logging;
using GFramework.Core.query;
using GFramework.Core.state;
using NUnit.Framework;
namespace GFramework.Core.Tests.state;
/// <summary>
/// ContextAwareStateMachine类的单元测试
/// 测试内容包括:
/// - 作为ISystem的集成测试
/// - Init方法 - 初始化上下文感知状态
/// - Init方法 - 设置Context属性
/// - Destroy方法 - 清理状态
/// - OnArchitecturePhase方法 - 接收架构阶段
/// - 上下文感知状态初始化
/// - 状态变更事件发送
/// - SetContext方法
/// - GetContext方法
/// - ISystem接口实现验证
/// - 与EventBus的集成测试
/// - 多状态注册和切换
/// - 状态机生命周期完整性
/// </summary>
[TestFixture]
public class StateMachineSystemTests
{
[SetUp]
public void SetUp()
{
// 初始化 LoggerFactoryResolver 以支持 IocContainer
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
_eventBus = new EventBus();
var container = new IocContainer();
// 直接初始化 logger 字段
var loggerField = typeof(IocContainer).GetField("_logger",
BindingFlags.NonPublic | BindingFlags.Instance);
loggerField?.SetValue(container,
LoggerFactoryResolver.Provider.CreateLogger(nameof(StateMachineSystemTests)));
container.RegisterPlurality(_eventBus);
container.RegisterPlurality(new CommandExecutor());
container.RegisterPlurality(new QueryExecutor());
container.RegisterPlurality(new DefaultEnvironment());
container.RegisterPlurality(new AsyncQueryExecutor());
_context = new ArchitectureContext(container);
_stateMachine = new TestStateMachineSystemV5();
_stateMachine.SetContext(_context);
}
private TestStateMachineSystemV5? _stateMachine;
private ArchitectureContext? _context;
private EventBus? _eventBus;
/// <summary>
/// 测试ContextAwareStateMachine实现ISystem接口
/// </summary>
[Test]
public void ContextAwareStateMachine_Should_Implement_ISystem_Interface()
{
Assert.That(_stateMachine, Is.InstanceOf<ISystem>());
}
/// <summary>
/// 测试SetContext设置Context属性
/// </summary>
[Test]
public void SetContext_Should_Set_Context_Property()
{
_stateMachine!.SetContext(_context!);
var context = _stateMachine.GetContext();
Assert.That(context, Is.SameAs(_context));
}
/// <summary>
/// 测试GetContext返回Context属性
/// </summary>
[Test]
public void GetContext_Should_Return_Context_Property()
{
_stateMachine!.SetContext(_context!);
var context = _stateMachine.GetContext();
Assert.That(context, Is.Not.Null);
Assert.That(context, Is.SameAs(_context));
}
/// <summary>
/// 测试Init方法为所有ContextAware状态设置Context
/// </summary>
[Test]
public void Init_Should_SetContext_On_All_ContextAware_States()
{
var state1 = new TestContextAwareStateV5();
var state2 = new TestContextAwareStateV5_2();
_stateMachine!.Register(state1);
_stateMachine.Register(state2);
Assert.That(state1.GetContext(), Is.Null);
Assert.That(state2.GetContext(), Is.Null);
_stateMachine.Init();
Assert.That(state1.GetContext(), Is.SameAs(_context));
Assert.That(state2.GetContext(), Is.SameAs(_context));
}
/// <summary>
/// 测试Init方法不为非ContextAware状态设置Context
/// </summary>
[Test]
public void Init_Should_Not_SetContext_On_NonContextAware_States()
{
var state = new TestStateV5();
_stateMachine!.Register(state);
_stateMachine.Init();
}
/// <summary>
/// 测试Destroy方法不抛出异常
/// </summary>
[Test]
public void Destroy_Should_Not_Throw_Exception()
{
Assert.That(() => _stateMachine!.Destroy(), Throws.Nothing);
}
/// <summary>
/// 测试OnArchitecturePhase方法不抛出异常
/// </summary>
[Test]
public void OnArchitecturePhase_Should_Not_Throw_Exception()
{
Assert.That(() => _stateMachine!.OnArchitecturePhase(ArchitecturePhase.Ready),
Throws.Nothing);
}
/// <summary>
/// 测试ChangeTo发送StateChangedEvent事件
/// 验证当状态机切换到新状态时会正确触发StateChangedEvent事件并且事件中的旧状态为null首次切换
/// </summary>
[Test]
public void ChangeTo_Should_Send_StateChangedEvent()
{
// 订阅StateChangedEvent事件以验证事件是否被正确发送
var eventReceived = false;
StateChangedEvent? receivedEvent = null;
_eventBus!.Register<StateChangedEvent>(e =>
{
eventReceived = true;
receivedEvent = e;
});
var state1 = new TestStateV5();
var state2 = new TestStateV5();
_stateMachine!.Register(state1);
_stateMachine.Register(state2);
_stateMachine.Init();
_stateMachine.ChangeTo<TestStateV5>();
Assert.That(eventReceived, Is.True);
Assert.That(receivedEvent!.OldState, Is.Null);
Assert.That(receivedEvent.NewState, Is.InstanceOf<TestStateV5>());
}
/// <summary>
/// 测试ChangeTo发送StateChangedEvent事件包含旧状态
/// 验证当状态机从一个状态切换到另一个状态时会正确触发StateChangedEvent事件
/// 并且事件中包含正确的旧状态和新状态信息
/// </summary>
[Test]
public void ChangeTo_Should_Send_StateChangedEvent_With_OldState()
{
// 订阅StateChangedEvent事件以验证事件是否被正确发送
var eventReceived = false;
StateChangedEvent? receivedEvent = null;
_eventBus!.Register<StateChangedEvent>(e =>
{
eventReceived = true;
receivedEvent = e;
});
var state1 = new TestStateV5();
var state2 = new TestStateV5();
_stateMachine!.Register(state1);
_stateMachine.Register(state2);
_stateMachine.Init();
_stateMachine.ChangeTo<TestStateV5>();
_stateMachine.ChangeTo<TestStateV5>();
Assert.That(eventReceived, Is.True);
Assert.That(receivedEvent!.OldState, Is.InstanceOf<TestStateV5>());
Assert.That(receivedEvent.NewState, Is.InstanceOf<TestStateV5>());
}
/// <summary>
/// 测试CanChangeTo方法对于已注册状态的工作情况
/// 验证当状态已注册到状态机中时CanChangeTo方法应返回true
/// </summary>
[Test]
public void CanChangeTo_Should_Work_With_Registered_States()
{
var state = new TestStateV5();
_stateMachine!.Register(state);
var canChange = _stateMachine.CanChangeTo<TestStateV5>();
Assert.That(canChange, Is.True);
}
/// <summary>
/// 测试可以注册多个状态
/// 验证状态机能够成功注册多个不同的状态实例,并且能够切换到这些已注册的状态
/// </summary>
[Test]
public void Multiple_States_Should_Be_Registered()
{
var state1 = new TestStateV5 { Id = 1 };
var state2 = new TestStateV5 { Id = 2 };
var state3 = new TestStateV5 { Id = 3 };
_stateMachine!.Register(state1);
_stateMachine.Register(state2);
_stateMachine.Register(state3);
var canChange = _stateMachine.CanChangeTo<TestStateV5>();
Assert.That(canChange, Is.True);
}
/// <summary>
/// 测试状态机生命周期完整
/// </summary>
[Test]
public void StateMachine_Lifecycle_Should_Be_Complete()
{
var state1 = new TestStateV5();
var state2 = new TestStateV5();
_stateMachine!.Register(state1);
_stateMachine.Register(state2);
_stateMachine.Init();
Assert.That(_stateMachine.Current, Is.Null);
_stateMachine.ChangeTo<TestStateV5>();
Assert.That(_stateMachine.Current, Is.InstanceOf<TestStateV5>());
_stateMachine.Destroy();
}
}
#region Test Classes
/// <summary>
/// 测试用的ContextAwareStateMachine派生类用于访问内部状态字典
/// </summary>
public class TestStateMachineSystemV5 : StateMachineSystem
{
/// <summary>
/// 获取状态机内部的状态字典
/// </summary>
/// <returns>类型到状态实例的映射字典</returns>
public Dictionary<Type, IState> GetStates()
{
return States;
}
}
/// <summary>
/// 测试用的上下文感知状态基类实现
/// </summary>
public class TestContextAwareStateV5 : ContextAwareStateBase
{
/// <summary>
/// 进入状态时调用
/// </summary>
/// <param name="previous">前一个状态</param>
public override void OnEnter(IState? previous)
{
}
/// <summary>
/// 退出状态时调用
/// </summary>
/// <param name="next">下一个状态</param>
public override void OnExit(IState? next)
{
}
}
/// <summary>
/// 第二个测试用的上下文感知状态基类实现
/// </summary>
public class TestContextAwareStateV5_2 : ContextAwareStateBase
{
/// <summary>
/// 进入状态时调用
/// </summary>
/// <param name="previous">前一个状态</param>
public override void OnEnter(IState? previous)
{
}
/// <summary>
/// 退出状态时调用
/// </summary>
/// <param name="next">下一个状态</param>
public override void OnExit(IState? next)
{
}
}
/// <summary>
/// 测试用的普通状态实现
/// </summary>
public class TestStateV5 : IState
{
/// <summary>
/// 状态标识符
/// </summary>
public int Id { get; set; }
/// <summary>
/// 检查是否可以转换到指定状态
/// </summary>
/// <param name="next">目标状态</param>
/// <returns>始终返回true表示允许转换</returns>
public bool CanTransitionTo(IState next)
{
return true;
}
/// <summary>
/// 进入状态时调用
/// </summary>
/// <param name="previous">前一个状态</param>
public void OnEnter(IState? previous)
{
}
/// <summary>
/// 退出状态时调用
/// </summary>
/// <param name="next">下一个状态</param>
public void OnExit(IState? next)
{
}
}
#endregion