diff --git a/GFramework.Core.Tests/architecture/ArchitectureConfigurationTests.cs b/GFramework.Core.Tests/architecture/ArchitectureConfigurationTests.cs index 5f77c81..30e3705 100644 --- a/GFramework.Core.Tests/architecture/ArchitectureConfigurationTests.cs +++ b/GFramework.Core.Tests/architecture/ArchitectureConfigurationTests.cs @@ -7,17 +7,31 @@ using NUnit.Framework; namespace GFramework.Core.Tests.architecture; +/// +/// ArchitectureConfiguration类的单元测试 +/// 测试内容包括: +/// - 构造函数默认值 +/// - LoggerProperties默认配置(ConsoleLoggerFactoryProvider + Info级别) +/// - ArchitectureProperties默认配置(AllowLateRegistration=false, StrictPhaseValidation=true) +/// - 自定义配置替换 +/// - LoggerProperties独立修改 +/// - ArchitectureProperties独立修改 +/// - IArchitectureConfiguration接口实现验证 +/// [TestFixture] public class ArchitectureConfigurationTests { - private ArchitectureConfiguration? _configuration; - [SetUp] public void SetUp() { _configuration = new ArchitectureConfiguration(); } + private ArchitectureConfiguration? _configuration; + + /// + /// 测试构造函数是否正确初始化LoggerProperties + /// [Test] public void Constructor_Should_Initialize_LoggerProperties_With_Default_Values() { @@ -25,121 +39,154 @@ public class ArchitectureConfigurationTests Assert.That(_configuration!.LoggerProperties, Is.Not.Null); } + /// + /// 测试LoggerProperties默认使用ConsoleLoggerFactoryProvider + /// [Test] public void LoggerProperties_Should_Use_ConsoleLoggerFactoryProvider_By_Default() { - Assert.That(_configuration!.LoggerProperties.LoggerFactoryProvider, + Assert.That(_configuration!.LoggerProperties.LoggerFactoryProvider, Is.InstanceOf()); } + /// + /// 测试LoggerProperties默认使用Info日志级别 + /// [Test] public void LoggerProperties_Should_Use_Info_LogLevel_By_Default() { - var consoleProvider = _configuration!.LoggerProperties.LoggerFactoryProvider + var consoleProvider = _configuration!.LoggerProperties.LoggerFactoryProvider as ConsoleLoggerFactoryProvider; - + Assert.That(consoleProvider, Is.Not.Null); Assert.That(consoleProvider!.MinLevel, Is.EqualTo(LogLevel.Info)); } + /// + /// 测试ArchitectureProperties的AllowLateRegistration默认为false + /// [Test] public void ArchitectureProperties_Should_Have_AllowLateRegistration_Set_To_False_By_Default() { - Assert.That(_configuration!.ArchitectureProperties.AllowLateRegistration, + Assert.That(_configuration!.ArchitectureProperties.AllowLateRegistration, Is.False); } + /// + /// 测试ArchitectureProperties的StrictPhaseValidation默认为true + /// [Test] public void ArchitectureProperties_Should_Have_StrictPhaseValidation_Set_To_True_By_Default() { - Assert.That(_configuration!.ArchitectureProperties.StrictPhaseValidation, + Assert.That(_configuration!.ArchitectureProperties.StrictPhaseValidation, Is.True); } + /// + /// 测试LoggerProperties可以被自定义配置替换 + /// [Test] public void LoggerProperties_Should_Be_Replaced_With_Custom_Configuration() { var customProvider = new ConsoleLoggerFactoryProvider { MinLevel = LogLevel.Debug }; - var customLoggerProperties = new LoggerProperties - { - LoggerFactoryProvider = customProvider + var customLoggerProperties = new LoggerProperties + { + LoggerFactoryProvider = customProvider }; - + _configuration!.LoggerProperties = customLoggerProperties; - + Assert.That(_configuration.LoggerProperties, Is.SameAs(customLoggerProperties)); - Assert.That(_configuration.LoggerProperties.LoggerFactoryProvider, + Assert.That(_configuration.LoggerProperties.LoggerFactoryProvider, Is.InstanceOf()); - var currentProvider = _configuration.LoggerProperties.LoggerFactoryProvider + var currentProvider = _configuration.LoggerProperties.LoggerFactoryProvider as ConsoleLoggerFactoryProvider; Assert.That(currentProvider!.MinLevel, Is.EqualTo(LogLevel.Debug)); } + /// + /// 测试ArchitectureProperties可以被自定义配置替换 + /// [Test] public void ArchitectureProperties_Should_Be_Replaced_With_Custom_Configuration() { - var customProperties = new ArchitectureProperties - { + var customProperties = new ArchitectureProperties + { AllowLateRegistration = true, StrictPhaseValidation = false }; - + _configuration!.ArchitectureProperties = customProperties; - + Assert.That(_configuration.ArchitectureProperties, Is.SameAs(customProperties)); - Assert.That(_configuration.ArchitectureProperties.AllowLateRegistration, + Assert.That(_configuration.ArchitectureProperties.AllowLateRegistration, Is.True); - Assert.That(_configuration.ArchitectureProperties.StrictPhaseValidation, + Assert.That(_configuration.ArchitectureProperties.StrictPhaseValidation, Is.False); } + /// + /// 测试LoggerProperties可以独立修改 + /// [Test] public void LoggerProperties_Should_Be_Modifiable_Independently() { - var originalProvider = _configuration!.LoggerProperties.LoggerFactoryProvider + var originalProvider = _configuration!.LoggerProperties.LoggerFactoryProvider as ConsoleLoggerFactoryProvider; - + originalProvider!.MinLevel = LogLevel.Debug; - - var modifiedProvider = _configuration.LoggerProperties.LoggerFactoryProvider + + var modifiedProvider = _configuration.LoggerProperties.LoggerFactoryProvider as ConsoleLoggerFactoryProvider; Assert.That(modifiedProvider!.MinLevel, Is.EqualTo(LogLevel.Debug)); } + /// + /// 测试ArchitectureProperties可以独立修改 + /// [Test] public void ArchitectureProperties_Should_Be_Modifiable_Independently() { _configuration!.ArchitectureProperties.AllowLateRegistration = true; _configuration.ArchitectureProperties.StrictPhaseValidation = false; - - Assert.That(_configuration.ArchitectureProperties.AllowLateRegistration, + + Assert.That(_configuration.ArchitectureProperties.AllowLateRegistration, Is.True); - Assert.That(_configuration.ArchitectureProperties.StrictPhaseValidation, + Assert.That(_configuration.ArchitectureProperties.StrictPhaseValidation, Is.False); } + /// + /// 测试ArchitectureConfiguration实现IArchitectureConfiguration接口 + /// [Test] public void ArchitectureConfiguration_Should_Implement_IArchitectureConfiguration_Interface() { Assert.That(_configuration, Is.InstanceOf()); } + /// + /// 测试新实例不与其他实例共享LoggerProperties + /// [Test] public void New_Instance_Should_Not_Share_LoggerProperties_With_Other_Instance() { var config1 = new ArchitectureConfiguration(); var config2 = new ArchitectureConfiguration(); - + Assert.That(config1.LoggerProperties, Is.Not.SameAs(config2.LoggerProperties)); } + /// + /// 测试新实例不与其他实例共享ArchitectureProperties + /// [Test] public void New_Instance_Should_Not_Share_ArchitectureProperties_With_Other_Instance() { var config1 = new ArchitectureConfiguration(); var config2 = new ArchitectureConfiguration(); - - Assert.That(config1.ArchitectureProperties, + + Assert.That(config1.ArchitectureProperties, Is.Not.SameAs(config2.ArchitectureProperties)); } -} +} \ No newline at end of file diff --git a/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs b/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs index 740412f..07e4d22 100644 --- a/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs +++ b/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs @@ -3,8 +3,6 @@ using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.command; using GFramework.Core.Abstractions.enums; using GFramework.Core.Abstractions.environment; -using GFramework.Core.Abstractions.events; -using GFramework.Core.Abstractions.ioc; using GFramework.Core.Abstractions.model; using GFramework.Core.Abstractions.query; using GFramework.Core.Abstractions.system; @@ -20,30 +18,45 @@ using NUnit.Framework; namespace GFramework.Core.Tests.architecture; +/// +/// ArchitectureContext类的单元测试 +/// 测试内容包括: +/// - 构造函数参数验证(所有5个参数) +/// - 构造函数空参数异常 +/// - SendQuery方法 - 正常查询发送 +/// - SendQuery方法 - 空查询异常 +/// - SendCommand方法 - 正常命令发送 +/// - SendCommand方法 - 空命令异常 +/// - SendCommand_WithResult方法 - 正常命令发送 +/// - SendCommand_WithResult方法 - 空命令异常 +/// - SendEvent方法 - 正常事件发送 +/// - SendEvent_WithInstance方法 - 正常事件发送 +/// - SendEvent_WithInstance方法 - 空事件异常 +/// - GetSystem方法 - 获取已注册系统 +/// - GetSystem方法 - 获取未注册系统 +/// - GetModel方法 - 获取已注册模型 +/// - GetModel方法 - 获取未注册模型 +/// - GetUtility方法 - 获取已注册工具 +/// - GetUtility方法 - 获取未注册工具 +/// - GetEnvironment方法 - 获取环境对象 +/// [TestFixture] public class ArchitectureContextTests { - private ArchitectureContext? _context; - private IocContainer? _container; - private EventBus? _eventBus; - private CommandBus? _commandBus; - private QueryBus? _queryBus; - private DefaultEnvironment? _environment; - [SetUp] public void SetUp() { // 初始化 LoggerFactoryResolver 以支持 IocContainer LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider(); - + _container = new IocContainer(); - + // 直接初始化 logger 字段 var loggerField = typeof(IocContainer).GetField("_logger", BindingFlags.NonPublic | BindingFlags.Instance); loggerField?.SetValue(_container, LoggerFactoryResolver.Provider.CreateLogger(nameof(ArchitectureContextTests))); - + _eventBus = new EventBus(); _commandBus = new CommandBus(); _queryBus = new QueryBus(); @@ -51,64 +64,98 @@ public class ArchitectureContextTests _context = new ArchitectureContext(_container, _eventBus, _commandBus, _queryBus, _environment); } + private ArchitectureContext? _context; + private IocContainer? _container; + private EventBus? _eventBus; + private CommandBus? _commandBus; + private QueryBus? _queryBus; + private DefaultEnvironment? _environment; + + /// + /// 测试构造函数在所有参数都有效时不应抛出异常 + /// [Test] public void Constructor_Should_NotThrow_When_AllParameters_AreValid() { - Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, _environment!), + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, _environment!), Throws.Nothing); } + /// + /// 测试构造函数在Container为null时应抛出ArgumentNullException + /// [Test] public void Constructor_Should_ThrowArgumentNullException_When_Container_IsNull() { - Assert.That(() => new ArchitectureContext(null!, _eventBus!, _commandBus!, _queryBus!, _environment!), + Assert.That(() => new ArchitectureContext(null!, _eventBus!, _commandBus!, _queryBus!, _environment!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("container")); } + /// + /// 测试构造函数在EventBus为null时应抛出ArgumentNullException + /// [Test] public void Constructor_Should_ThrowArgumentNullException_When_EventBus_IsNull() { - Assert.That(() => new ArchitectureContext(_container!, null!, _commandBus!, _queryBus!, _environment!), + Assert.That(() => new ArchitectureContext(_container!, null!, _commandBus!, _queryBus!, _environment!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("eventBus")); } + /// + /// 测试构造函数在CommandBus为null时应抛出ArgumentNullException + /// [Test] public void Constructor_Should_ThrowArgumentNullException_When_CommandBus_IsNull() { - Assert.That(() => new ArchitectureContext(_container!, _eventBus!, null!, _queryBus!, _environment!), + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, null!, _queryBus!, _environment!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("commandBus")); } + /// + /// 测试构造函数在QueryBus为null时应抛出ArgumentNullException + /// [Test] public void Constructor_Should_ThrowArgumentNullException_When_QueryBus_IsNull() { - Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, null!, _environment!), + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, null!, _environment!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("queryBus")); } + /// + /// 测试构造函数在Environment为null时应抛出ArgumentNullException + /// [Test] public void Constructor_Should_ThrowArgumentNullException_When_Environment_IsNull() { - Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, null!), + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, null!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("environment")); } + /// + /// 测试SendQuery方法在查询有效时返回正确结果 + /// [Test] public void SendQuery_Should_ReturnResult_When_Query_IsValid() { var testQuery = new TestQueryV2 { Result = 42 }; var result = _context!.SendQuery(testQuery); - + Assert.That(result, Is.EqualTo(42)); } + /// + /// 测试SendQuery方法在查询为null时应抛出ArgumentNullException + /// [Test] public void SendQuery_Should_ThrowArgumentNullException_When_Query_IsNull() { - Assert.That(() => _context!.SendQuery(null!), + Assert.That(() => _context!.SendQuery(null!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("query")); } + /// + /// 测试SendCommand方法在命令有效时正确执行 + /// [Test] public void SendCommand_Should_ExecuteCommand_When_Command_IsValid() { @@ -117,39 +164,54 @@ public class ArchitectureContextTests Assert.That(testCommand.Executed, Is.True); } + /// + /// 测试SendCommand方法在命令为null时应抛出ArgumentNullException + /// [Test] public void SendCommand_Should_ThrowArgumentNullException_When_Command_IsNull() { - Assert.That(() => _context!.SendCommand((ICommand)null!), + Assert.That(() => _context!.SendCommand((ICommand)null!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("command")); } + /// + /// 测试SendCommand方法(带返回值)在命令有效时返回正确结果 + /// [Test] public void SendCommand_WithResult_Should_ReturnResult_When_Command_IsValid() { var testCommand = new TestCommandWithResultV2 { Result = 123 }; var result = _context!.SendCommand(testCommand); - + Assert.That(result, Is.EqualTo(123)); } + /// + /// 测试SendCommand方法(带返回值)在命令为null时应抛出ArgumentNullException + /// [Test] public void SendCommand_WithResult_Should_ThrowArgumentNullException_When_Command_IsNull() { - Assert.That(() => _context!.SendCommand((ICommand)null!), + Assert.That(() => _context!.SendCommand((ICommand)null!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("command")); } + /// + /// 测试SendEvent方法在事件类型有效时正确发送事件 + /// [Test] public void SendEvent_Should_SendEvent_When_EventType_IsValid() { bool eventReceived = false; _context!.RegisterEvent(_ => eventReceived = true); _context.SendEvent(); - + Assert.That(eventReceived, Is.True); } + /// + /// 测试SendEvent方法(带实例)在事件实例有效时正确发送事件 + /// [Test] public void SendEvent_WithInstance_Should_SendEvent_When_EventInstance_IsValid() { @@ -157,82 +219,106 @@ public class ArchitectureContextTests var testEvent = new TestEventV2(); _context!.RegisterEvent(_ => eventReceived = true); _context.SendEvent(testEvent); - + Assert.That(eventReceived, Is.True); } + /// + /// 测试SendEvent方法(带实例)在事件实例为null时应抛出ArgumentNullException + /// [Test] public void SendEvent_WithInstance_Should_ThrowArgumentNullException_When_EventInstance_IsNull() { - Assert.That(() => _context!.SendEvent(null!), + Assert.That(() => _context!.SendEvent(null!), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("e")); } + /// + /// 测试GetSystem方法在系统已注册时返回注册的系统 + /// [Test] public void GetSystem_Should_ReturnRegisteredSystem_When_SystemIsRegistered() { var testSystem = new TestSystemV2(); _container!.RegisterPlurality(testSystem); - + var result = _context!.GetSystem(); - + Assert.That(result, Is.Not.Null); Assert.That(result, Is.SameAs(testSystem)); } + /// + /// 测试GetSystem方法在系统未注册时返回null + /// [Test] public void GetSystem_Should_ReturnNull_When_SystemIsNotRegistered() { var result = _context!.GetSystem(); - + Assert.That(result, Is.Null); } + /// + /// 测试GetModel方法在模型已注册时返回注册的模型 + /// [Test] public void GetModel_Should_ReturnRegisteredModel_When_ModelIsRegistered() { var testModel = new TestModelV2(); _container!.RegisterPlurality(testModel); - + var result = _context!.GetModel(); - + Assert.That(result, Is.Not.Null); Assert.That(result, Is.SameAs(testModel)); } + /// + /// 测试GetModel方法在模型未注册时返回null + /// [Test] public void GetModel_Should_ReturnNull_When_ModelIsNotRegistered() { var result = _context!.GetModel(); - + Assert.That(result, Is.Null); } + /// + /// 测试GetUtility方法在工具已注册时返回注册的工具 + /// [Test] public void GetUtility_Should_ReturnRegisteredUtility_When_UtilityIsRegistered() { var testUtility = new TestUtilityV2(); _container!.RegisterPlurality(testUtility); - + var result = _context!.GetUtility(); - + Assert.That(result, Is.Not.Null); Assert.That(result, Is.SameAs(testUtility)); } + /// + /// 测试GetUtility方法在工具未注册时返回null + /// [Test] public void GetUtility_Should_ReturnNull_When_UtilityIsNotRegistered() { var result = _context!.GetUtility(); - + Assert.That(result, Is.Null); } + /// + /// 测试GetEnvironment方法返回环境实例 + /// [Test] public void GetEnvironment_Should_Return_EnvironmentInstance() { var environment = _context!.GetEnvironment(); - + Assert.That(environment, Is.Not.Null); Assert.That(environment, Is.InstanceOf()); } @@ -244,42 +330,66 @@ public class TestSystemV2 : ISystem { private IArchitectureContext _context = null!; public int Id { get; init; } - + public void SetContext(IArchitectureContext context) => _context = context; public IArchitectureContext GetContext() => _context; - public void Init() { } - public void Destroy() { } - public void OnArchitecturePhase(ArchitecturePhase phase) { } + + public void Init() + { + } + + public void Destroy() + { + } + + public void OnArchitecturePhase(ArchitecturePhase phase) + { + } } public class TestModelV2 : IModel { private IArchitectureContext _context = null!; public int Id { get; init; } - + public void SetContext(IArchitectureContext context) => _context = context; public IArchitectureContext GetContext() => _context; - public void Init() { } - public void Destroy() { } - public void OnArchitecturePhase(ArchitecturePhase phase) { } + + public void Init() + { + } + + public void OnArchitecturePhase(ArchitecturePhase phase) + { + } + + public void Destroy() + { + } } public class TestUtilityV2 : IUtility { private IArchitectureContext _context = null!; public int Id { get; init; } - + public void SetContext(IArchitectureContext context) => _context = context; public IArchitectureContext GetContext() => _context; - public void Init() { } - public void Destroy() { } + + public void Init() + { + } + + public void Destroy() + { + } } public class TestQueryV2 : IQuery { private IArchitectureContext _context = null!; public int Result { get; init; } - + public int Do() => Result; public void SetContext(IArchitectureContext context) => _context = context; public IArchitectureContext GetContext() => _context; @@ -289,7 +399,7 @@ public class TestCommandV2 : ICommand { private IArchitectureContext _context = null!; public bool Executed { get; private set; } - + public void Execute() => Executed = true; public void SetContext(IArchitectureContext context) => _context = context; public IArchitectureContext GetContext() => _context; @@ -299,7 +409,7 @@ public class TestCommandWithResultV2 : ICommand { private IArchitectureContext _context = null!; public int Result { get; init; } - + public int Execute() => Result; public void SetContext(IArchitectureContext context) => _context = context; public IArchitectureContext GetContext() => _context; @@ -310,4 +420,4 @@ public class TestEventV2 public int Data { get; init; } } -#endregion +#endregion \ No newline at end of file diff --git a/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs b/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs index fffa567..3995f71 100644 --- a/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs +++ b/GFramework.Core.Tests/architecture/ArchitectureServicesTests.cs @@ -1,4 +1,3 @@ -using System; using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.command; using GFramework.Core.Abstractions.environment; @@ -18,12 +17,22 @@ using NUnit.Framework; namespace GFramework.Core.Tests.architecture; +/// +/// ArchitectureServices类的单元测试 +/// 测试内容包括: +/// - 服务容器初始化 +/// - 所有服务实例创建(Container, EventBus, CommandBus, QueryBus) +/// - SetContext方法 - 设置上下文 +/// - SetContext方法 - 重复设置上下文 +/// - GetContext方法 - 获取已设置上下文 +/// - GetContext方法 - 未设置上下文时返回null +/// - 上下文传播到容器 +/// - IArchitectureServices接口实现验证 +/// - 服务独立性验证(多个实例) +/// [TestFixture] public class ArchitectureServicesTests { - private ArchitectureServices? _services; - private TestArchitectureContextV3? _context; - [SetUp] public void SetUp() { @@ -31,6 +40,12 @@ public class ArchitectureServicesTests _context = new TestArchitectureContextV3(); } + private ArchitectureServices? _services; + private TestArchitectureContextV3? _context; + + /// + /// 测试构造函数初始化所有服务 + /// [Test] public void Constructor_Should_Initialize_AllServices() { @@ -47,6 +62,9 @@ public class ArchitectureServicesTests Assert.That(_services.Container, Is.InstanceOf()); } + /// + /// 测试EventBus是EventBus的实例 + /// [Test] public void EventBus_Should_Be_Instance_Of_EventBus() { @@ -54,6 +72,9 @@ public class ArchitectureServicesTests Assert.That(_services.EventBus, Is.InstanceOf()); } + /// + /// 测试CommandBus是CommandBus的实例 + /// [Test] public void CommandBus_Should_Be_Instance_Of_CommandBus() { @@ -61,6 +82,9 @@ public class ArchitectureServicesTests Assert.That(_services.CommandBus, Is.InstanceOf()); } + /// + /// 测试QueryBus是QueryBus的实例 + /// [Test] public void QueryBus_Should_Be_Instance_Of_QueryBus() { @@ -68,94 +92,124 @@ public class ArchitectureServicesTests Assert.That(_services.QueryBus, Is.InstanceOf()); } + /// + /// 测试SetContext设置内部Context字段 + /// [Test] public void SetContext_Should_Set_Context_Internal_Field() { _services!.SetContext(_context!); - + var context = _services.GetContext(); Assert.That(context, Is.SameAs(_context)); } + /// + /// 测试SetContext将上下文传播到Container + /// [Test] public void SetContext_Should_Propagate_Context_To_Container() { _services!.SetContext(_context!); - + var containerContext = _services.Container.GetContext(); Assert.That(containerContext, Is.SameAs(_context)); } + /// + /// 测试GetContext在SetContext后返回上下文 + /// [Test] public void GetContext_Should_Return_Context_After_SetContext() { _services!.SetContext(_context!); - + var context = _services.GetContext(); Assert.That(context, Is.Not.Null); Assert.That(context, Is.SameAs(_context)); } + /// + /// 测试GetContext在未设置上下文时返回null + /// [Test] public void GetContext_Should_ReturnNull_When_Context_Not_Set() { var context = _services!.GetContext(); - + Assert.That(context, Is.Null); } + /// + /// 测试SetContext替换已存在的上下文 + /// [Test] public void SetContext_Should_Replace_Existing_Context() { var context1 = new TestArchitectureContextV3 { Id = 1 }; var context2 = new TestArchitectureContextV3 { Id = 2 }; - + _services!.SetContext(context1); _services.SetContext(context2); - + var context = _services.GetContext(); Assert.That(context, Is.SameAs(context2)); } + /// + /// 测试ArchitectureServices实现IArchitectureServices接口 + /// [Test] public void ArchitectureServices_Should_Implement_IArchitectureServices_Interface() { Assert.That(_services, Is.InstanceOf()); } + /// + /// 测试多个实例有独立的Container + /// [Test] public void Multiple_Instances_Should_Have_Independent_Container() { var services1 = new ArchitectureServices(); var services2 = new ArchitectureServices(); - + Assert.That(services1.Container, Is.Not.SameAs(services2.Container)); } + /// + /// 测试多个实例有独立的EventBus + /// [Test] public void Multiple_Instances_Should_Have_Independent_EventBus() { var services1 = new ArchitectureServices(); var services2 = new ArchitectureServices(); - + Assert.That(services1.EventBus, Is.Not.SameAs(services2.EventBus)); } + /// + /// 测试多个实例有独立的CommandBus + /// [Test] public void Multiple_Instances_Should_Have_Independent_CommandBus() { var services1 = new ArchitectureServices(); var services2 = new ArchitectureServices(); - + Assert.That(services1.CommandBus, Is.Not.SameAs(services2.CommandBus)); } + /// + /// 测试多个实例有独立的QueryBus + /// [Test] public void Multiple_Instances_Should_Have_Independent_QueryBus() { var services1 = new ArchitectureServices(); var services2 = new ArchitectureServices(); - + Assert.That(services1.QueryBus, Is.Not.SameAs(services2.QueryBus)); } } @@ -167,12 +221,12 @@ public class TestArchitectureContextV3 : IArchitectureContext private readonly IocContainer _container = new(); private readonly DefaultEnvironment _environment = new(); public int Id { get; init; } - + public IIocContainer Container => _container; public IEventBus EventBus => new EventBus(); public ICommandBus CommandBus => new CommandBus(); public IQueryBus QueryBus => new QueryBus(); - + public TModel? GetModel() where TModel : class, IModel => _container.Get(); public TSystem? GetSystem() where TSystem : class, ISystem => _container.Get(); public TUtility? GetUtility() where TUtility : class, IUtility => _container.Get(); @@ -200,4 +254,4 @@ public class TestArchitectureContextV3 : IArchitectureContext public IEnvironment GetEnvironment() => _environment; } -#endregion +#endregion \ No newline at end of file diff --git a/GFramework.Core.Tests/architecture/GameContextTests.cs b/GFramework.Core.Tests/architecture/GameContextTests.cs index fb89558..2dc63a5 100644 --- a/GFramework.Core.Tests/architecture/GameContextTests.cs +++ b/GFramework.Core.Tests/architecture/GameContextTests.cs @@ -17,21 +17,46 @@ using NUnit.Framework; namespace GFramework.Core.Tests.architecture; +/// +/// GameContext类的单元测试 +/// 测试内容包括: +/// - ArchitectureReadOnlyDictionary在启动时为空 +/// - Bind方法添加上下文到字典 +/// - Bind重复类型时抛出异常 +/// - GetByType返回正确的上下文 +/// - GetByType未找到时抛出异常 +/// - Get泛型方法返回正确的上下文 +/// - TryGet方法在找到时返回true +/// - TryGet方法在未找到时返回false +/// - GetFirstArchitectureContext在存在时返回 +/// - GetFirstArchitectureContext为空时抛出异常 +/// - Unbind移除上下文 +/// - Clear移除所有上下文 +/// [TestFixture] public class GameContextTests { + /// + /// 测试初始化方法,在每个测试方法执行前清空GameContext + /// [SetUp] public void SetUp() { GameContext.Clear(); } + /// + /// 测试清理方法,在每个测试方法执行后清空GameContext + /// [TearDown] public void TearDown() { GameContext.Clear(); } + /// + /// 测试ArchitectureReadOnlyDictionary在启动时返回空字典 + /// [Test] public void ArchitectureReadOnlyDictionary_Should_Return_Empty_At_Start() { @@ -40,6 +65,9 @@ public class GameContextTests Assert.That(dict.Count, Is.EqualTo(0)); } + /// + /// 测试Bind方法是否正确将上下文添加到字典中 + /// [Test] public void Bind_Should_Add_Context_To_Dictionary() { @@ -50,6 +78,9 @@ public class GameContextTests Assert.That(GameContext.ArchitectureReadOnlyDictionary.Count, Is.EqualTo(1)); } + /// + /// 测试Bind方法在绑定重复类型时是否抛出InvalidOperationException异常 + /// [Test] public void Bind_WithDuplicateType_Should_ThrowInvalidOperationException() { @@ -62,6 +93,9 @@ public class GameContextTests GameContext.Bind(typeof(TestArchitecture), context2)); } + /// + /// 测试GetByType方法是否返回正确的上下文 + /// [Test] public void GetByType_Should_Return_Correct_Context() { @@ -73,6 +107,9 @@ public class GameContextTests Assert.That(result, Is.SameAs(context)); } + /// + /// 测试GetByType方法在未找到对应类型时是否抛出InvalidOperationException异常 + /// [Test] public void GetByType_Should_Throw_When_Not_Found() { @@ -80,6 +117,9 @@ public class GameContextTests GameContext.GetByType(typeof(TestArchitecture))); } + /// + /// 测试Get泛型方法是否返回正确的上下文 + /// [Test] public void GetGeneric_Should_Return_Correct_Context() { @@ -91,6 +131,9 @@ public class GameContextTests Assert.That(result, Is.SameAs(context)); } + /// + /// 测试TryGet方法在找到上下文时是否返回true并正确设置输出参数 + /// [Test] public void TryGet_Should_ReturnTrue_When_Found() { @@ -103,6 +146,9 @@ public class GameContextTests Assert.That(foundContext, Is.SameAs(context)); } + /// + /// 测试TryGet方法在未找到上下文时是否返回false且输出参数为null + /// [Test] public void TryGet_Should_ReturnFalse_When_Not_Found() { @@ -112,6 +158,9 @@ public class GameContextTests Assert.That(foundContext, Is.Null); } + /// + /// 测试GetFirstArchitectureContext方法在存在上下文时是否返回正确的上下文 + /// [Test] public void GetFirstArchitectureContext_Should_Return_When_Exists() { @@ -123,6 +172,9 @@ public class GameContextTests Assert.That(result, Is.SameAs(context)); } + /// + /// 测试GetFirstArchitectureContext方法在没有上下文时是否抛出InvalidOperationException异常 + /// [Test] public void GetFirstArchitectureContext_Should_Throw_When_Empty() { @@ -130,6 +182,9 @@ public class GameContextTests GameContext.GetFirstArchitectureContext()); } + /// + /// 测试Unbind方法是否正确移除指定类型的上下文 + /// [Test] public void Unbind_Should_Remove_Context() { @@ -141,6 +196,9 @@ public class GameContextTests Assert.That(GameContext.ArchitectureReadOnlyDictionary.Count, Is.EqualTo(0)); } + /// + /// 测试Clear方法是否正确移除所有上下文 + /// [Test] public void Clear_Should_Remove_All_Contexts() { @@ -153,46 +211,133 @@ public class GameContextTests } } +/// +/// 测试用的架构类,继承自Architecture +/// public class TestArchitecture : Architecture { + /// + /// 初始化方法,当前为空实现 + /// protected override void Init() { } } +/// +/// 测试用的架构上下文类,实现了IArchitectureContext接口 +/// public class TestArchitectureContext : IArchitectureContext { private readonly IocContainer _container = new(); + /// + /// 获取依赖注入容器 + /// public IIocContainer Container => _container; + + /// + /// 获取事件总线 + /// public IEventBus EventBus => new EventBus(); + + /// + /// 获取命令总线 + /// public ICommandBus CommandBus => new CommandBus(); + + /// + /// 获取查询总线 + /// public IQueryBus QueryBus => new QueryBus(); + + /// + /// 获取环境对象 + /// public IEnvironment Environment => new DefaultEnvironment(); + /// + /// 获取指定类型的模型 + /// + /// 模型类型 + /// 模型实例或null public TModel? GetModel() where TModel : class, IModel => _container.Get(); + + /// + /// 获取指定类型的系统 + /// + /// 系统类型 + /// 系统实例或null public TSystem? GetSystem() where TSystem : class, ISystem => _container.Get(); + + /// + /// 获取指定类型的工具 + /// + /// 工具类型 + /// 工具实例或null public TUtility? GetUtility() where TUtility : class, IUtility => _container.Get(); + /// + /// 发送事件 + /// + /// 事件类型 public void SendEvent() where TEvent : new() { } + /// + /// 发送事件 + /// + /// 事件类型 + /// 事件实例 public void SendEvent(TEvent e) where TEvent : class { } + /// + /// 注册事件处理器 + /// + /// 事件类型 + /// 事件处理委托 + /// 取消注册接口 public IUnRegister RegisterEvent(Action handler) => new DefaultUnRegister(() => { }); + /// + /// 取消注册事件处理器 + /// + /// 事件类型 + /// 事件处理委托 public void UnRegisterEvent(Action onEvent) { } + /// + /// 发送命令 + /// + /// 命令对象 public void SendCommand(ICommand command) { } + /// + /// 发送带返回值的命令 + /// + /// 返回值类型 + /// 命令对象 + /// 命令执行结果 public TResult SendCommand(ICommand command) => default!; + + /// + /// 发送查询请求 + /// + /// 查询结果类型 + /// 查询对象 + /// 查询结果 public TResult SendQuery(IQuery query) => default!; + + /// + /// 获取环境对象 + /// + /// 环境对象 public IEnvironment GetEnvironment() => Environment; } \ No newline at end of file diff --git a/GFramework.Core.Tests/command/CommandBusTests.cs b/GFramework.Core.Tests/command/CommandBusTests.cs index 5b1be15..51d9bef 100644 --- a/GFramework.Core.Tests/command/CommandBusTests.cs +++ b/GFramework.Core.Tests/command/CommandBusTests.cs @@ -4,6 +4,14 @@ using NUnit.Framework; namespace GFramework.Core.Tests.command; +/// +/// CommandBus类的单元测试 +/// 测试内容包括: +/// - Send方法执行命令 +/// - Send方法处理null命令 +/// - Send方法(带返回值)返回值 +/// - Send方法(带返回值)处理null命令 +/// [TestFixture] public class CommandBusTests { @@ -15,6 +23,9 @@ public class CommandBusTests private CommandBus _commandBus = null!; + /// + /// 测试Send方法执行命令 + /// [Test] public void Send_Should_Execute_Command() { @@ -26,12 +37,18 @@ public class CommandBusTests Assert.That(command.ExecutedValue, Is.EqualTo(42)); } + /// + /// 测试Send方法处理null命令时抛出ArgumentNullException异常 + /// [Test] public void Send_WithNullCommand_Should_ThrowArgumentNullException() { Assert.Throws(() => _commandBus.Send(null!)); } + /// + /// 测试Send方法(带返回值)正确返回值 + /// [Test] public void Send_WithResult_Should_Return_Value() { @@ -44,6 +61,9 @@ public class CommandBusTests Assert.That(result, Is.EqualTo(200)); } + /// + /// 测试Send方法(带返回值)处理null命令时抛出ArgumentNullException异常 + /// [Test] public void Send_WithResult_AndNullCommand_Should_ThrowArgumentNullException() { @@ -51,20 +71,44 @@ public class CommandBusTests } } +/// +/// 测试用命令输入类,实现ICommandInput接口 +/// public sealed class TestCommandInput : ICommandInput { + /// + /// 获取或设置值 + /// public int Value { get; init; } } +/// +/// 测试用命令类,继承AbstractCommand +/// public sealed class TestCommand : AbstractCommand { + /// + /// 构造函数 + /// + /// 命令输入 public TestCommand(TestCommandInput input) : base(input) { } + /// + /// 获取命令是否已执行 + /// public bool Executed { get; private set; } + + /// + /// 获取执行的值 + /// public int ExecutedValue { get; private set; } + /// + /// 执行命令的重写方法 + /// + /// 命令输入 protected override void OnExecute(TestCommandInput input) { Executed = true; @@ -72,14 +116,29 @@ public sealed class TestCommand : AbstractCommand } } +/// +/// 测试用带返回值的命令类,继承AbstractCommand +/// public sealed class TestCommandWithResult : AbstractCommand { + /// + /// 构造函数 + /// + /// 命令输入 public TestCommandWithResult(TestCommandInput input) : base(input) { } + /// + /// 获取命令是否已执行 + /// public bool Executed { get; private set; } + /// + /// 执行命令并返回结果的重写方法 + /// + /// 命令输入 + /// 执行结果 protected override int OnExecute(TestCommandInput input) { Executed = true; diff --git a/GFramework.Core.Tests/environment/EnvironmentTests.cs b/GFramework.Core.Tests/environment/EnvironmentTests.cs index e77c619..5de91ef 100644 --- a/GFramework.Core.Tests/environment/EnvironmentTests.cs +++ b/GFramework.Core.Tests/environment/EnvironmentTests.cs @@ -4,9 +4,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.environment; +/// +/// 测试环境相关的单元测试类,用于验证环境管理功能的正确性 +/// [TestFixture] public class EnvironmentTests { + /// + /// 在每个测试方法执行前进行初始化设置 + /// [SetUp] public void SetUp() { @@ -16,6 +22,9 @@ public class EnvironmentTests private TestEnvironment _environment = null!; + /// + /// 验证默认环境的名称是否正确返回"Default" + /// [Test] public void DefaultEnvironment_Name_Should_ReturnDefault() { @@ -24,6 +33,9 @@ public class EnvironmentTests Assert.That(env.Name, Is.EqualTo("Default")); } + /// + /// 验证默认环境的初始化方法不会抛出异常 + /// [Test] public void DefaultEnvironment_Initialize_Should_NotThrow() { @@ -32,6 +44,9 @@ public class EnvironmentTests Assert.DoesNotThrow(() => env.Initialize()); } + /// + /// 验证当键存在时Get方法应该返回正确的值 + /// [Test] public void Get_Should_Return_Value_When_Key_Exists() { @@ -42,6 +57,9 @@ public class EnvironmentTests Assert.That(result, Is.EqualTo("testValue")); } + /// + /// 验证当键不存在时Get方法应该返回null + /// [Test] public void Get_Should_ReturnNull_When_Key_Not_Exists() { @@ -50,6 +68,9 @@ public class EnvironmentTests Assert.That(result, Is.Null); } + /// + /// 验证当类型不匹配时Get方法应该返回null + /// [Test] public void Get_Should_ReturnNull_When_Type_Does_Not_Match() { @@ -60,6 +81,9 @@ public class EnvironmentTests Assert.That(result, Is.Null); } + /// + /// 验证当键存在时TryGet方法应该返回true并输出正确的值 + /// [Test] public void TryGet_Should_ReturnTrue_And_Value_When_Key_Exists() { @@ -71,6 +95,9 @@ public class EnvironmentTests Assert.That(value, Is.EqualTo("testValue")); } + /// + /// 验证当键不存在时TryGet方法应该返回false且输出值为null + /// [Test] public void TryGet_Should_ReturnFalse_When_Key_Not_Exists() { @@ -80,6 +107,9 @@ public class EnvironmentTests Assert.That(value, Is.Null); } + /// + /// 验证当类型不匹配时TryGet方法应该返回false且输出值为null + /// [Test] public void TryGet_Should_ReturnFalse_When_Type_Does_Not_Match() { @@ -91,6 +121,9 @@ public class EnvironmentTests Assert.That(value, Is.Null); } + /// + /// 验证当键存在时GetRequired方法应该返回正确的值 + /// [Test] public void GetRequired_Should_Return_Value_When_Key_Exists() { @@ -101,6 +134,9 @@ public class EnvironmentTests Assert.That(result, Is.EqualTo("testValue")); } + /// + /// 验证当键不存在时GetRequired方法应该抛出InvalidOperationException异常 + /// [Test] public void GetRequired_Should_ThrowInvalidOperationException_When_Key_Not_Exists() { @@ -108,6 +144,9 @@ public class EnvironmentTests _environment.GetRequired("nonExistentKey")); } + /// + /// 验证Register方法应该将值添加到字典中 + /// [Test] public void Register_Should_Add_Value_To_Dictionary() { @@ -118,6 +157,9 @@ public class EnvironmentTests Assert.That(result, Is.EqualTo("newValue")); } + /// + /// 验证Register方法应该覆盖已存在的值 + /// [Test] public void Register_Should_Overwrite_Existing_Value() { @@ -129,6 +171,9 @@ public class EnvironmentTests Assert.That(result, Is.EqualTo("value2")); } + /// + /// 验证通过IEnvironment接口的Register方法应该能够添加值 + /// [Test] public void IEnvironment_Register_Should_Add_Value() { @@ -141,15 +186,29 @@ public class EnvironmentTests } } +/// +/// 测试环境实现类,继承自EnvironmentBase +/// public class TestEnvironment : EnvironmentBase { + /// + /// 获取环境名称 + /// public override string Name { get; } = "TestEnvironment"; + /// + /// 注册键值对到环境中 + /// + /// 要注册的键 + /// 要注册的值 public new void Register(string key, object value) { base.Register(key, value); } + /// + /// 初始化环境 + /// public override void Initialize() { } diff --git a/GFramework.Core.Tests/events/ArchitectureEventsTests.cs b/GFramework.Core.Tests/events/ArchitectureEventsTests.cs index d308cf9..2f96153 100644 --- a/GFramework.Core.Tests/events/ArchitectureEventsTests.cs +++ b/GFramework.Core.Tests/events/ArchitectureEventsTests.cs @@ -1,137 +1,173 @@ -using System; using GFramework.Core.events; using NUnit.Framework; namespace GFramework.Core.Tests.events; +/// +/// ArchitectureEvents类的单元测试 +/// 测试内容包括: +/// - ArchitectureLifecycleReadyEvent事件触发 +/// - ArchitectureDestroyingEvent事件触发 +/// - ArchitectureDestroyedEvent事件触发 +/// - ArchitectureFailedInitializationEvent事件触发 +/// - 事件的参数传递 +/// - 事件的订阅和取消订阅 +/// - 事件顺序验证(LifecycleReady -> Destroying -> Destroyed) +/// [TestFixture] public class ArchitectureEventsTests { - private EventBus? _eventBus; - [SetUp] public void SetUp() { _eventBus = new EventBus(); } + private EventBus? _eventBus; + + /// + /// 测试ArchitectureLifecycleReadyEvent事件可以创建并发送 + /// [Test] public void ArchitectureLifecycleReadyEvent_Should_Be_Created_And_Sent() { bool eventReceived = false; - + _eventBus!.Register(_ => eventReceived = true); _eventBus.Send(); - + Assert.That(eventReceived, Is.True); } + /// + /// 测试ArchitectureDestroyingEvent事件可以创建并发送 + /// [Test] public void ArchitectureDestroyingEvent_Should_Be_Created_And_Sent() { bool eventReceived = false; - + _eventBus!.Register(_ => eventReceived = true); _eventBus.Send(); - + Assert.That(eventReceived, Is.True); } + /// + /// 测试ArchitectureDestroyedEvent事件可以创建并发送 + /// [Test] public void ArchitectureDestroyedEvent_Should_Be_Created_And_Sent() { bool eventReceived = false; - + _eventBus!.Register(_ => eventReceived = true); _eventBus.Send(); - + Assert.That(eventReceived, Is.True); } + /// + /// 测试ArchitectureFailedInitializationEvent事件可以创建并发送 + /// [Test] public void ArchitectureFailedInitializationEvent_Should_Be_Created_And_Sent() { bool eventReceived = false; - + _eventBus!.Register(_ => eventReceived = true); _eventBus.Send(); - + Assert.That(eventReceived, Is.True); } + /// + /// 测试事件按正确顺序发送 + /// [Test] public void Events_Should_Be_Sent_In_Correct_Order() { var events = new List(); - + _eventBus!.Register(_ => events.Add("Ready")); _eventBus!.Register(_ => events.Add("Destroying")); _eventBus!.Register(_ => events.Add("Destroyed")); - + _eventBus.Send(); _eventBus.Send(); _eventBus.Send(); - + Assert.That(events.Count, Is.EqualTo(3)); Assert.That(events[0], Is.EqualTo("Ready")); Assert.That(events[1], Is.EqualTo("Destroying")); Assert.That(events[2], Is.EqualTo("Destroyed")); } + /// + /// 测试多个订阅者都能接收到事件 + /// [Test] public void Multiple_Subscribers_Should_All_Receive_Events() { var count1 = 0; var count2 = 0; - + _eventBus!.Register(_ => count1++); _eventBus!.Register(_ => count2++); - + _eventBus.Send(); - + Assert.That(count1, Is.EqualTo(1)); Assert.That(count2, Is.EqualTo(1)); } + /// + /// 测试事件取消订阅后不再接收未来事件 + /// [Test] public void Event_UnRegister_Should_Prevent_Future_Events() { var count = 0; var unregister = _eventBus!.Register(_ => count++); - + _eventBus.Send(); Assert.That(count, Is.EqualTo(1)); - + unregister.UnRegister(); _eventBus.Send(); - + Assert.That(count, Is.EqualTo(1)); } + /// + /// 测试不同类型事件互不干扰 + /// [Test] public void Different_Events_Should_Not_Interfere() { bool readyReceived = false; bool destroyingReceived = false; - + _eventBus!.Register(_ => readyReceived = true); _eventBus!.Register(_ => destroyingReceived = true); - + _eventBus.Send(); - + Assert.That(readyReceived, Is.True); Assert.That(destroyingReceived, Is.False); - + _eventBus.Send(); - + Assert.That(destroyingReceived, Is.True); } + /// + /// 测试事件可以在没有订阅者时发送 + /// [Test] public void Event_Can_Be_Sent_Without_Subscribers() { - Assert.That(() => _eventBus!.Send(), + Assert.That(() => _eventBus!.Send(), Throws.Nothing); } -} - +} \ No newline at end of file diff --git a/GFramework.Core.Tests/events/EasyEventsTests.cs b/GFramework.Core.Tests/events/EasyEventsTests.cs index 8c72f75..7c8e1e0 100644 --- a/GFramework.Core.Tests/events/EasyEventsTests.cs +++ b/GFramework.Core.Tests/events/EasyEventsTests.cs @@ -3,9 +3,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.events; +/// +/// EasyEvents功能测试类,用于验证事件系统的注册、触发和参数传递功能 +/// [TestFixture] public class EasyEventsTests { + /// + /// 测试用例初始化方法,在每个测试方法执行前设置EasyEvents实例 + /// [SetUp] public void SetUp() { @@ -14,6 +20,9 @@ public class EasyEventsTests private EasyEvents _easyEvents = null!; + /// + /// 测试单参数事件的功能,验证事件能够正确接收并传递int类型参数 + /// [Test] public void Get_EventT_Should_Trigger_With_Parameter() { @@ -21,11 +30,16 @@ public class EasyEventsTests var @event = EasyEvents.GetOrAdd>(); @event.Register(value => { receivedValue = value; }); + + // 触发事件并传递参数42 @event.Trigger(42); Assert.That(receivedValue, Is.EqualTo(42)); } + /// + /// 测试双参数事件的功能,验证事件能够正确接收并传递int和string类型的参数 + /// [Test] public void Get_EventTTK_Should_Trigger_With_Two_Parameters() { @@ -38,6 +52,8 @@ public class EasyEventsTests receivedInt = i; receivedString = s; }); + + // 触发事件并传递两个参数:整数100和字符串"hello" @event.Trigger(100, "hello"); Assert.That(receivedInt, Is.EqualTo(100)); diff --git a/GFramework.Core.Tests/events/EventBusTests.cs b/GFramework.Core.Tests/events/EventBusTests.cs index 608d1bb..bb9fd5d 100644 --- a/GFramework.Core.Tests/events/EventBusTests.cs +++ b/GFramework.Core.Tests/events/EventBusTests.cs @@ -3,9 +3,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.events; +/// +/// EventBus测试类,用于验证事件总线的各种功能 +/// [TestFixture] public class EventBusTests { + /// + /// 测试设置方法,在每个测试方法执行前初始化EventBus实例 + /// [SetUp] public void SetUp() { @@ -14,6 +20,10 @@ public class EventBusTests private EventBus _eventBus = null!; + /// + /// 测试注册事件处理器的功能 + /// 验证注册的处理器能够在发送对应事件时被正确调用 + /// [Test] public void Register_Should_Add_Handler() { @@ -25,6 +35,10 @@ public class EventBusTests Assert.That(called, Is.True); } + /// + /// 测试注销事件处理器的功能 + /// 验证已注册的处理器在注销后不会再被调用 + /// [Test] public void UnRegister_Should_Remove_Handler() { @@ -33,13 +47,19 @@ public class EventBusTests Action handler = @event => { count++; }; _eventBus.Register(handler); _eventBus.Send(); + // 验证处理器被调用一次 Assert.That(count, Is.EqualTo(1)); _eventBus.UnRegister(handler); _eventBus.Send(); + // 验证处理器在注销后不再被调用 Assert.That(count, Is.EqualTo(1)); } + /// + /// 测试发送事件时调用所有处理器的功能 + /// 验证同一事件类型的多个处理器都能被正确调用 + /// [Test] public void SendEvent_Should_Invoke_All_Handlers() { @@ -51,11 +71,15 @@ public class EventBusTests _eventBus.Send(); + // 验证所有处理器都被调用一次 Assert.That(count1, Is.EqualTo(1)); Assert.That(count2, Is.EqualTo(1)); } } +/// +/// EventBus测试专用事件类 +/// public class EventBusTestsEvent { } \ No newline at end of file diff --git a/GFramework.Core.Tests/events/EventTests.cs b/GFramework.Core.Tests/events/EventTests.cs index 8a5bd6b..6f13af4 100644 --- a/GFramework.Core.Tests/events/EventTests.cs +++ b/GFramework.Core.Tests/events/EventTests.cs @@ -3,9 +3,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.events; +/// +/// 测试事件系统功能的测试类 +/// [TestFixture] public class EventTests { + /// + /// 在每个测试方法执行前进行初始化设置 + /// [SetUp] public void SetUp() { @@ -18,6 +24,9 @@ public class EventTests private Event _eventInt = null!; private Event _eventIntString = null!; + /// + /// 测试EasyEvent注册功能是否正确添加处理器 + /// [Test] public void EasyEvent_Register_Should_Add_Handler() { @@ -29,6 +38,9 @@ public class EventTests Assert.That(called, Is.True); } + /// + /// 测试EasyEvent取消注册功能是否正确移除处理器 + /// [Test] public void EasyEvent_UnRegister_Should_Remove_Handler() { @@ -44,6 +56,9 @@ public class EventTests Assert.That(count, Is.EqualTo(1)); } + /// + /// 测试EasyEvent多个处理器是否都能被调用 + /// [Test] public void EasyEvent_Multiple_Handlers_Should_All_Be_Called() { @@ -59,6 +74,9 @@ public class EventTests Assert.That(count2, Is.EqualTo(1)); } + /// + /// 测试带泛型参数的事件注册功能是否正确添加处理器 + /// [Test] public void EventT_Register_Should_Add_Handler() { @@ -70,6 +88,9 @@ public class EventTests Assert.That(receivedValue, Is.EqualTo(42)); } + /// + /// 测试带泛型参数的事件取消注册功能是否正确移除处理器 + /// [Test] public void EventT_UnRegister_Should_Remove_Handler() { @@ -85,6 +106,9 @@ public class EventTests Assert.That(count, Is.EqualTo(1)); } + /// + /// 测试带泛型参数的事件多个处理器是否都能被调用 + /// [Test] public void EventT_Multiple_Handlers_Should_All_Be_Called() { @@ -100,6 +124,9 @@ public class EventTests Assert.That(values, Does.Contain(10)); } + /// + /// 测试带两个泛型参数的事件注册功能是否正确添加处理器 + /// [Test] public void EventTTK_Register_Should_Add_Handler() { @@ -117,6 +144,9 @@ public class EventTests Assert.That(receivedString, Is.EqualTo("test")); } + /// + /// 测试带两个泛型参数的事件取消注册功能是否正确移除处理器 + /// [Test] public void EventTTK_UnRegister_Should_Remove_Handler() { diff --git a/GFramework.Core.Tests/events/OrEventTests.cs b/GFramework.Core.Tests/events/OrEventTests.cs index 51fa4ab..79a553a 100644 --- a/GFramework.Core.Tests/events/OrEventTests.cs +++ b/GFramework.Core.Tests/events/OrEventTests.cs @@ -3,9 +3,16 @@ using NUnit.Framework; namespace GFramework.Core.Tests.events; +/// +/// 测试OrEvent类的功能,验证其在多个事件中的逻辑或操作行为 +/// [TestFixture] public class OrEventTests { + /// + /// 测试当任意一个事件触发时,OrEvent应该被触发 + /// 验证基本的OR逻辑功能 + /// [Test] public void OrEvent_Should_Trigger_When_Any_Event_Fires() { @@ -16,6 +23,7 @@ public class OrEventTests var triggered = false; orEvent.Register(() => { triggered = true; }); + // 将两个事件添加到OrEvent中 orEvent.Or(event1).Or(event2); event1.Trigger(0); @@ -23,6 +31,10 @@ public class OrEventTests Assert.That(triggered, Is.True); } + /// + /// 测试当第二个事件触发时,OrEvent应该被触发 + /// 验证OR逻辑对所有注册事件都有效 + /// [Test] public void OrEvent_Should_Trigger_When_Second_Event_Fires() { @@ -33,6 +45,7 @@ public class OrEventTests var triggered = false; orEvent.Register(() => { triggered = true; }); + // 将两个事件添加到OrEvent中 orEvent.Or(event1).Or(event2); event2.Trigger(0); @@ -40,6 +53,10 @@ public class OrEventTests Assert.That(triggered, Is.True); } + /// + /// 测试OrEvent支持多个处理程序 + /// 验证单个OrEvent可以注册多个回调函数 + /// [Test] public void OrEvent_Should_Support_Multiple_Handlers() { @@ -52,6 +69,7 @@ public class OrEventTests orEvent.Register(() => { count1++; }); orEvent.Register(() => { count2++; }); + // 将事件添加到OrEvent中 orEvent.Or(@event); @event.Trigger(0); @@ -59,6 +77,10 @@ public class OrEventTests Assert.That(count2, Is.EqualTo(1)); } + /// + /// 测试UnRegister方法应该移除处理程序 + /// 验证注销功能能够正确移除已注册的回调函数 + /// [Test] public void OrEvent_UnRegister_Should_Remove_Handler() { @@ -74,6 +96,7 @@ public class OrEventTests @event.Trigger(0); Assert.That(count, Is.EqualTo(1)); + // 注销处理程序 orEvent.UnRegister(handler); @event.Trigger(0); Assert.That(count, Is.EqualTo(1)); diff --git a/GFramework.Core.Tests/events/UnRegisterTests.cs b/GFramework.Core.Tests/events/UnRegisterTests.cs index 8a5ed78..516818b 100644 --- a/GFramework.Core.Tests/events/UnRegisterTests.cs +++ b/GFramework.Core.Tests/events/UnRegisterTests.cs @@ -4,9 +4,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.events; +/// +/// 注销功能测试类,用于测试不同类型的注销行为 +/// [TestFixture] public class UnRegisterTests { + /// + /// 测试DefaultUnRegister在调用注销时是否正确触发回调函数 + /// [Test] public void DefaultUnRegister_Should_InvokeCallback_When_UnRegisterCalled() { @@ -18,6 +24,9 @@ public class UnRegisterTests Assert.That(invoked, Is.True); } + /// + /// 测试DefaultUnRegister在注销后是否清除回调函数,防止重复执行 + /// [Test] public void DefaultUnRegister_Should_ClearCallback_After_UnRegister() { @@ -30,6 +39,9 @@ public class UnRegisterTests Assert.That(callCount, Is.EqualTo(1)); } + /// + /// 测试DefaultUnRegister在传入空回调函数时不会抛出异常 + /// [Test] public void DefaultUnRegister_WithNullCallback_Should_NotThrow() { @@ -38,6 +50,9 @@ public class UnRegisterTests Assert.DoesNotThrow(() => unRegister.UnRegister()); } + /// + /// 测试BindablePropertyUnRegister是否能正确从属性中注销事件处理器 + /// [Test] public void BindablePropertyUnRegister_Should_UnRegister_From_Property() { @@ -55,6 +70,9 @@ public class UnRegisterTests Assert.That(callCount, Is.EqualTo(0)); } + /// + /// 测试BindablePropertyUnRegister在注销后是否清除内部引用 + /// [Test] public void BindablePropertyUnRegister_Should_Clear_References() { @@ -65,10 +83,14 @@ public class UnRegisterTests unRegister.UnRegister(); + // 验证注销后引用被清除 Assert.That(unRegister.BindableProperty, Is.Null); Assert.That(unRegister.OnValueChanged, Is.Null); } + /// + /// 测试BindablePropertyUnRegister在传入空属性时不会抛出异常 + /// [Test] public void BindablePropertyUnRegister_WithNull_Property_Should_NotThrow() { @@ -78,6 +100,9 @@ public class UnRegisterTests Assert.DoesNotThrow(() => unRegister.UnRegister()); } + /// + /// 测试BindablePropertyUnRegister在传入空处理器时不会抛出异常 + /// [Test] public void BindablePropertyUnRegister_WithNull_Handler_Should_NotThrow() { diff --git a/GFramework.Core.Tests/extensions/ObjectExtensionsTests.cs b/GFramework.Core.Tests/extensions/ObjectExtensionsTests.cs index b2d5433..24dce89 100644 --- a/GFramework.Core.Tests/extensions/ObjectExtensionsTests.cs +++ b/GFramework.Core.Tests/extensions/ObjectExtensionsTests.cs @@ -3,9 +3,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.extensions; +/// +/// 测试ObjectExtensions扩展方法的功能 +/// [TestFixture] public class ObjectExtensionsTests { + /// + /// 验证IfType方法在类型匹配时执行指定操作 + /// [Test] public void IfType_Should_Execute_Action_When_Type_Matches() { @@ -17,6 +23,9 @@ public class ObjectExtensionsTests Assert.That(executed, Is.True); } + /// + /// 验证IfType方法在类型不匹配时不执行指定操作 + /// [Test] public void IfType_Should_Not_Execute_Action_When_Type_Does_Not_Match() { @@ -28,6 +37,9 @@ public class ObjectExtensionsTests Assert.That(executed, Is.False); } + /// + /// 验证IfType方法在类型匹配且谓词条件为真时执行指定操作 + /// [Test] public void IfType_WithPredicate_Should_Execute_When_Type_Matches_And_Predicate_True() { @@ -39,6 +51,9 @@ public class ObjectExtensionsTests Assert.That(executed, Is.True); } + /// + /// 验证IfType方法在谓词条件为假时不执行指定操作 + /// [Test] public void IfType_WithPredicate_Should_Not_Execute_When_Predicate_False() { @@ -50,6 +65,9 @@ public class ObjectExtensionsTests Assert.That(executed, Is.False); } + /// + /// 验证IfType方法在类型匹配时执行匹配操作,在类型不匹配时执行不匹配操作 + /// [Test] public void IfType_WithBoth_Actions_Should_Execute_Correct_Action() { @@ -66,6 +84,9 @@ public class ObjectExtensionsTests Assert.That(noMatchCount, Is.EqualTo(0)); } + /// + /// 验证IfType方法在类型匹配时返回转换结果 + /// [Test] public void IfType_WithResult_Should_Return_Value_When_Type_Matches() { @@ -76,6 +97,9 @@ public class ObjectExtensionsTests Assert.That(result, Is.EqualTo("Test")); } + /// + /// 验证IfType方法在类型不匹配时返回默认值 + /// [Test] public void IfType_WithResult_Should_Return_Default_When_Type_Does_Not_Match() { @@ -86,6 +110,9 @@ public class ObjectExtensionsTests Assert.That(result, Is.Null); } + /// + /// 验证As方法在类型匹配时返回实例 + /// [Test] public void As_Should_Return_Instance_When_Type_Matches() { @@ -97,6 +124,9 @@ public class ObjectExtensionsTests Assert.That(result, Is.SameAs(obj)); } + /// + /// 验证As方法在类型不匹配时返回null + /// [Test] public void As_Should_Return_Null_When_Type_Does_Not_Match() { @@ -107,6 +137,9 @@ public class ObjectExtensionsTests Assert.That(result, Is.Null); } + /// + /// 验证Do方法执行操作并返回对象本身 + /// [Test] public void Do_Should_Execute_Action_And_Return_Object() { @@ -118,6 +151,9 @@ public class ObjectExtensionsTests Assert.That(obj.Value, Is.EqualTo(10)); } + /// + /// 验证Do方法支持链式调用 + /// [Test] public void Do_Should_Support_Chaining() { @@ -130,6 +166,9 @@ public class ObjectExtensionsTests Assert.That(obj.Name, Is.EqualTo("B")); } + /// + /// 验证SwitchType方法执行匹配的处理器 + /// [Test] public void SwitchType_Should_Execute_Matching_Handler() { @@ -144,6 +183,9 @@ public class ObjectExtensionsTests Assert.That(executed, Is.True); } + /// + /// 验证SwitchType方法只执行第一个匹配的处理器 + /// [Test] public void SwitchType_Should_Execute_First_Matching_Handler() { @@ -158,6 +200,9 @@ public class ObjectExtensionsTests Assert.That(count, Is.EqualTo(1)); } + /// + /// 验证SwitchType方法在没有匹配项时不执行任何处理器 + /// [Test] public void SwitchType_Should_Not_Execute_When_No_Match() { @@ -173,8 +218,18 @@ public class ObjectExtensionsTests } } +/// +/// 测试用的简单类 +/// public class TestClass { + /// + /// 获取或设置整数值 + /// public int Value { get; set; } + + /// + /// 获取或设置名称字符串 + /// public string Name { get; set; } = string.Empty; } \ No newline at end of file diff --git a/GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs b/GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs index 73fea1c..4e389d4 100644 --- a/GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs +++ b/GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs @@ -5,9 +5,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.extensions; +/// +/// 测试UnRegisterList扩展方法的功能 +/// [TestFixture] public class UnRegisterListExtensionTests { + /// + /// 在每个测试方法执行前初始化测试环境 + /// [SetUp] public void SetUp() { @@ -16,6 +22,9 @@ public class UnRegisterListExtensionTests private TestUnRegisterList _unRegisterList = null!; + /// + /// 验证AddToUnregisterList方法能够正确将元素添加到列表中 + /// [Test] public void AddToUnregisterList_Should_Add_To_List() { @@ -26,6 +35,9 @@ public class UnRegisterListExtensionTests Assert.That(_unRegisterList.UnregisterList.Count, Is.EqualTo(1)); } + /// + /// 验证AddToUnregisterList方法能够正确添加多个元素到列表中 + /// [Test] public void AddToUnregisterList_Should_Add_Multiple_Elements() { @@ -40,6 +52,9 @@ public class UnRegisterListExtensionTests Assert.That(_unRegisterList.UnregisterList.Count, Is.EqualTo(3)); } + /// + /// 验证UnRegisterAll方法能够正确注销所有元素 + /// [Test] public void UnRegisterAll_Should_UnRegister_All_Elements() { @@ -55,6 +70,7 @@ public class UnRegisterListExtensionTests unRegister2.AddToUnregisterList(_unRegisterList); unRegister3.AddToUnregisterList(_unRegisterList); + // 执行注销操作 _unRegisterList.UnRegisterAll(); Assert.That(invoked1, Is.True); @@ -62,23 +78,33 @@ public class UnRegisterListExtensionTests Assert.That(invoked3, Is.True); } + /// + /// 验证UnRegisterAll方法在执行后会清空列表 + /// [Test] public void UnRegisterAll_Should_Clear_List() { var unRegister = new DefaultUnRegister(() => { }); unRegister.AddToUnregisterList(_unRegisterList); + // 执行注销操作 _unRegisterList.UnRegisterAll(); Assert.That(_unRegisterList.UnregisterList.Count, Is.EqualTo(0)); } + /// + /// 验证UnRegisterAll方法在空列表情况下不会抛出异常 + /// [Test] public void UnRegisterAll_Should_Not_Throw_When_Empty() { Assert.DoesNotThrow(() => _unRegisterList.UnRegisterAll()); } + /// + /// 验证UnRegisterAll方法对每个元素只调用一次注销操作 + /// [Test] public void UnRegisterAll_Should_Invoke_Once_Per_Element() { @@ -87,13 +113,20 @@ public class UnRegisterListExtensionTests unRegister.AddToUnregisterList(_unRegisterList); + // 执行注销操作 _unRegisterList.UnRegisterAll(); Assert.That(callCount, Is.EqualTo(1)); } } +/// +/// 测试用的UnRegisterList实现类,用于验证扩展方法功能 +/// public class TestUnRegisterList : IUnRegisterList { + /// + /// 获取或设置注销列表 + /// public IList UnregisterList { get; } = new List(); } \ No newline at end of file diff --git a/GFramework.Core.Tests/ioc/IocContainerTests.cs b/GFramework.Core.Tests/ioc/IocContainerTests.cs index 207a456..8f4aad2 100644 --- a/GFramework.Core.Tests/ioc/IocContainerTests.cs +++ b/GFramework.Core.Tests/ioc/IocContainerTests.cs @@ -6,9 +6,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.ioc; +/// +/// 测试 IoC 容器功能的单元测试类 +/// [TestFixture] public class IocContainerTests { + /// + /// 在每个测试方法执行前进行设置 + /// [SetUp] public void SetUp() { @@ -26,6 +32,9 @@ public class IocContainerTests private IocContainer _container = null!; private readonly Dictionary _mockContextServices = new(); + /// + /// 测试注册单例实例的功能 + /// [Test] public void RegisterSingleton_Should_Register_Instance() { @@ -34,6 +43,9 @@ public class IocContainerTests Assert.DoesNotThrow(() => _container.RegisterSingleton(instance)); } + /// + /// 测试重复注册单例时应抛出 InvalidOperationException 异常 + /// [Test] public void RegisterSingleton_WithDuplicate_Should_ThrowInvalidOperationException() { @@ -45,6 +57,9 @@ public class IocContainerTests Assert.Throws(() => _container.RegisterSingleton(instance2)); } + /// + /// 测试在容器冻结后注册单例时应抛出 InvalidOperationException 异常 + /// [Test] public void RegisterSingleton_AfterFreeze_Should_ThrowInvalidOperationException() { @@ -54,6 +69,9 @@ public class IocContainerTests Assert.Throws(() => _container.RegisterSingleton(instance)); } + /// + /// 测试注册多样性实例到所有类型的功能 + /// [Test] public void RegisterPlurality_Should_Register_Instance_To_All_Types() { @@ -65,6 +83,9 @@ public class IocContainerTests Assert.That(_container.Contains(), Is.True); } + /// + /// 测试在容器冻结后注册多样性实例时应抛出 InvalidOperationException 异常 + /// [Test] public void RegisterPlurality_AfterFreeze_Should_ThrowInvalidOperationException() { @@ -74,6 +95,9 @@ public class IocContainerTests Assert.Throws(() => _container.RegisterPlurality(instance)); } + /// + /// 测试泛型注册实例的功能 + /// [Test] public void Register_Generic_Should_Register_Instance() { @@ -84,6 +108,9 @@ public class IocContainerTests Assert.That(_container.Contains(), Is.True); } + /// + /// 测试在容器冻结后使用泛型注册时应抛出 InvalidOperationException 异常 + /// [Test] public void Register_Generic_AfterFreeze_Should_ThrowInvalidOperationException() { @@ -93,6 +120,9 @@ public class IocContainerTests Assert.Throws(() => _container.Register(instance)); } + /// + /// 测试按类型注册实例的功能 + /// [Test] public void Register_Type_Should_Register_Instance() { @@ -103,6 +133,9 @@ public class IocContainerTests Assert.That(_container.Contains(), Is.True); } + /// + /// 测试获取第一个实例的功能 + /// [Test] public void Get_Should_Return_First_Instance() { @@ -115,6 +148,9 @@ public class IocContainerTests Assert.That(result, Is.SameAs(instance)); } + /// + /// 测试当没有实例时获取应返回 null 的功能 + /// [Test] public void Get_WithNoInstances_Should_ReturnNull() { @@ -123,6 +159,9 @@ public class IocContainerTests Assert.That(result, Is.Null); } + /// + /// 测试获取必需的单个实例的功能 + /// [Test] public void GetRequired_Should_Return_Single_Instance() { @@ -135,12 +174,18 @@ public class IocContainerTests Assert.That(result, Is.SameAs(instance)); } + /// + /// 测试当没有实例时获取必需实例应抛出 InvalidOperationException 异常 + /// [Test] public void GetRequired_WithNoInstances_Should_ThrowInvalidOperationException() { Assert.Throws(() => _container.GetRequired()); } + /// + /// 测试当有多个实例时获取必需实例应抛出 InvalidOperationException 异常 + /// [Test] public void GetRequired_WithMultipleInstances_Should_ThrowInvalidOperationException() { @@ -150,6 +195,9 @@ public class IocContainerTests Assert.Throws(() => _container.GetRequired()); } + /// + /// 测试获取所有实例的功能 + /// [Test] public void GetAll_Should_Return_All_Instances() { @@ -166,6 +214,9 @@ public class IocContainerTests Assert.That(results, Does.Contain(instance2)); } + /// + /// 测试当没有实例时获取所有实例应返回空数组的功能 + /// [Test] public void GetAll_WithNoInstances_Should_Return_Empty_Array() { @@ -174,6 +225,9 @@ public class IocContainerTests Assert.That(results.Count, Is.EqualTo(0)); } + /// + /// 测试获取排序后的所有实例的功能 + /// [Test] public void GetAllSorted_Should_Return_Sorted_Instances() { @@ -189,6 +243,9 @@ public class IocContainerTests Assert.That(results[2].Priority, Is.EqualTo(3)); } + /// + /// 测试当存在实例时检查包含关系应返回 true 的功能 + /// [Test] public void Contains_WithExistingInstance_Should_ReturnTrue() { @@ -198,12 +255,18 @@ public class IocContainerTests Assert.That(_container.Contains(), Is.True); } + /// + /// 测试当不存在实例时检查包含关系应返回 false 的功能 + /// [Test] public void Contains_WithNoInstances_Should_ReturnFalse() { Assert.That(_container.Contains(), Is.False); } + /// + /// 测试当实例存在时检查实例包含关系应返回 true 的功能 + /// [Test] public void ContainsInstance_WithExistingInstance_Should_ReturnTrue() { @@ -213,6 +276,9 @@ public class IocContainerTests Assert.That(_container.ContainsInstance(instance), Is.True); } + /// + /// 测试当实例不存在时检查实例包含关系应返回 false 的功能 + /// [Test] public void ContainsInstance_WithNonExistingInstance_Should_ReturnFalse() { @@ -221,6 +287,9 @@ public class IocContainerTests Assert.That(_container.ContainsInstance(instance), Is.False); } + /// + /// 测试清除所有实例的功能 + /// [Test] public void Clear_Should_Remove_All_Instances() { @@ -232,6 +301,9 @@ public class IocContainerTests Assert.That(_container.Contains(), Is.False); } + /// + /// 测试冻结容器以防止进一步注册的功能 + /// [Test] public void Freeze_Should_Prevent_Further_Registrations() { @@ -243,6 +315,9 @@ public class IocContainerTests Assert.Throws(() => _container.Register(instance2)); } + /// + /// 测试注册系统实例的功能 + /// [Test] public void RegisterSystem_Should_Register_Instance() { @@ -254,9 +329,18 @@ public class IocContainerTests } } +/// +/// 服务接口定义 +/// public interface IService; +/// +/// 测试服务类,实现 IService 接口 +/// public sealed class TestService : IService { + /// + /// 获取或设置优先级 + /// public int Priority { get; set; } } \ No newline at end of file diff --git a/GFramework.Core.Tests/logging/ConsoleLoggerTests.cs b/GFramework.Core.Tests/logging/ConsoleLoggerTests.cs index 52a2de0..7fc7054 100644 --- a/GFramework.Core.Tests/logging/ConsoleLoggerTests.cs +++ b/GFramework.Core.Tests/logging/ConsoleLoggerTests.cs @@ -4,9 +4,16 @@ using NUnit.Framework; namespace GFramework.Core.Tests.logging; +/// +/// 测试ConsoleLogger类的功能和行为的单元测试类 +/// [TestFixture] public class ConsoleLoggerTests { + /// + /// 在每个测试方法执行前设置测试环境 + /// 创建StringWriter和ConsoleLogger实例用于测试 + /// [SetUp] public void SetUp() { @@ -14,6 +21,10 @@ public class ConsoleLoggerTests _logger = new ConsoleLogger("TestLogger", LogLevel.Info, _stringWriter, false); } + /// + /// 在每个测试方法执行后清理测试资源 + /// 释放StringWriter资源 + /// [TearDown] public void TearDown() { @@ -23,6 +34,10 @@ public class ConsoleLoggerTests private StringWriter _stringWriter = null!; private ConsoleLogger _logger = null!; + /// + /// 测试使用默认名称构造函数时是否正确使用根日志器名称 + /// 验证当未指定名称时,日志器使用"ROOT"作为默认名称 + /// [Test] public void Constructor_WithDefaultName_ShouldUseRootLoggerName() { @@ -31,6 +46,10 @@ public class ConsoleLoggerTests Assert.That(defaultLogger.Name(), Is.EqualTo("ROOT")); } + /// + /// 测试使用自定义名称构造函数时是否正确使用自定义名称 + /// 验证构造函数能够正确设置并返回指定的日志器名称 + /// [Test] public void Constructor_WithCustomName_ShouldUseCustomName() { @@ -39,6 +58,10 @@ public class ConsoleLoggerTests Assert.That(customLogger.Name(), Is.EqualTo("CustomLogger")); } + /// + /// 测试使用自定义最小级别构造函数时是否正确遵循最小日志级别 + /// 验证只有达到或超过最小级别的日志消息才会被记录 + /// [Test] public void Constructor_WithCustomMinLevel_ShouldRespectMinLevel() { @@ -52,6 +75,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Not.Contain("TRACE")); } + /// + /// 测试使用自定义写入器构造函数时是否将日志写入到自定义写入器 + /// 验证日志消息能够正确写入到指定的StringWriter中 + /// [Test] public void Constructor_WithCustomWriter_ShouldWriteToCustomWriter() { @@ -61,6 +88,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("Test message")); } + /// + /// 测试写入操作是否包含时间戳信息 + /// 验证每条日志消息都包含格式化的日期时间信息 + /// [Test] public void Write_ShouldIncludeTimestamp() { @@ -70,6 +101,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Match(@"\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\]")); } + /// + /// 测试写入操作是否包含日志级别信息 + /// 验证不同级别的日志消息都能正确显示对应的级别标识 + /// [Test] public void Write_ShouldIncludeLevel() { @@ -84,6 +119,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("ERROR")); } + /// + /// 测试写入操作是否包含日志器名称 + /// 验证日志输出中包含创建时指定的日志器名称 + /// [Test] public void Write_ShouldIncludeLoggerName() { @@ -93,6 +132,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("[TestLogger]")); } + /// + /// 测试写入操作在包含异常时是否正确包含异常信息 + /// 验证异常的详细信息能够正确记录在日志中 + /// [Test] public void Write_WithException_ShouldIncludeException() { @@ -104,6 +147,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("Test exception")); } + /// + /// 测试写入多行日志时是否正确格式化 + /// 验证多条日志消息能够正确分行显示且包含正确的级别信息 + /// [Test] public void Write_WithMultipleLines_ShouldFormatCorrectly() { @@ -120,6 +167,10 @@ public class ConsoleLoggerTests Assert.That(lines[2], Does.Contain("ERROR")); } + /// + /// 测试写入格式化消息时是否正确格式化 + /// 验证带参数的消息格式化功能正常工作 + /// [Test] public void Write_WithFormattedMessage_ShouldFormatCorrectly() { @@ -129,6 +180,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("Value: 42")); } + /// + /// 测试写入操作是否遵循最小日志级别限制 + /// 验证低于最小级别的日志消息不会被记录 + /// [Test] public void Write_ShouldRespectMinLevel() { @@ -142,6 +197,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Not.Contain("Trace message")); } + /// + /// 测试启用颜色功能时是否不影响输出内容 + /// 验证即使颜色功能被禁用,日志内容仍然正确记录 + /// [Test] public void Write_WithColorsEnabled_ShouldNotAffectOutputContent() { @@ -153,6 +212,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("Colored message")); } + /// + /// 测试所有日志级别是否都能正确格式化 + /// 验证从Trace到Fatal的所有日志级别都能正确显示 + /// [Test] public void Write_AllLogLevels_ShouldFormatCorrectly() { @@ -170,6 +233,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("FATAL")); } + /// + /// 测试写入嵌套异常时是否包含完整的异常信息 + /// 验证嵌套异常的所有层级信息都能被正确记录 + /// [Test] public void Write_WithNestedException_ShouldIncludeFullException() { @@ -184,6 +251,10 @@ public class ConsoleLoggerTests Assert.That(output, Does.Contain("Inner exception")); } + /// + /// 测试使用空写入器时是否不会抛出异常 + /// 验证当传入null写入器时,日志器能够安全处理而不崩溃 + /// [Test] public void Write_WithNullWriter_ShouldNotThrow() { @@ -192,6 +263,10 @@ public class ConsoleLoggerTests Assert.DoesNotThrow(() => logger.Info("Test message")); } + /// + /// 测试写入空消息时是否仍能正常写入 + /// 验证即使消息为空字符串,日志框架仍能生成包含其他信息的完整日志条目 + /// [Test] public void Write_WithEmptyMessage_ShouldStillWrite() { diff --git a/GFramework.Core.Tests/logging/LoggerFactoryTests.cs b/GFramework.Core.Tests/logging/LoggerFactoryTests.cs index cd03b0c..43b2b23 100644 --- a/GFramework.Core.Tests/logging/LoggerFactoryTests.cs +++ b/GFramework.Core.Tests/logging/LoggerFactoryTests.cs @@ -4,9 +4,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.logging; +/// +/// 测试LoggerFactory相关功能的测试类 +/// [TestFixture] public class LoggerFactoryTests { + /// + /// 测试ConsoleLoggerFactory的GetLogger方法是否返回ConsoleLogger实例 + /// [Test] public void ConsoleLoggerFactory_GetLogger_ShouldReturnConsoleLogger() { @@ -18,6 +24,9 @@ public class LoggerFactoryTests Assert.That(logger.Name(), Is.EqualTo("TestLogger")); } + /// + /// 测试ConsoleLoggerFactory使用不同名称获取不同的logger实例 + /// [Test] public void ConsoleLoggerFactory_GetLogger_WithDifferentNames_ShouldReturnDifferentLoggers() { @@ -29,6 +38,9 @@ public class LoggerFactoryTests Assert.That(logger2.Name(), Is.EqualTo("Logger2")); } + /// + /// 测试ConsoleLoggerFactory使用默认最小级别时的行为(默认为Info级别) + /// [Test] public void ConsoleLoggerFactory_GetLogger_WithDefaultMinLevel_ShouldUseInfo() { @@ -38,6 +50,7 @@ public class LoggerFactoryTests var stringWriter = new StringWriter(); var testLogger = new ConsoleLogger("TestLogger", LogLevel.Info, stringWriter, false); + // 验证Debug消息不会被记录,但Info消息会被记录 testLogger.Debug("Debug message"); testLogger.Info("Info message"); @@ -46,6 +59,9 @@ public class LoggerFactoryTests Assert.That(output, Does.Contain("Info message")); } + /// + /// 测试ConsoleLoggerFactoryProvider创建logger时使用提供者的最小级别设置 + /// [Test] public void ConsoleLoggerFactoryProvider_CreateLogger_ShouldReturnLoggerWithProviderMinLevel() { @@ -55,6 +71,7 @@ public class LoggerFactoryTests var stringWriter = new StringWriter(); var testLogger = new ConsoleLogger("TestLogger", LogLevel.Debug, stringWriter, false); + // 验证Debug消息会被记录,但Trace消息不会被记录 testLogger.Debug("Debug message"); testLogger.Trace("Trace message"); @@ -63,6 +80,9 @@ public class LoggerFactoryTests Assert.That(output, Does.Not.Contain("Trace message")); } + /// + /// 测试ConsoleLoggerFactoryProvider创建logger时使用提供的名称 + /// [Test] public void ConsoleLoggerFactoryProvider_CreateLogger_ShouldUseProvidedName() { @@ -72,6 +92,9 @@ public class LoggerFactoryTests Assert.That(logger.Name(), Is.EqualTo("MyLogger")); } + /// + /// 测试LoggerFactoryResolver的Provider属性是否有默认值 + /// [Test] public void LoggerFactoryResolver_Provider_ShouldHaveDefaultValue() { @@ -79,6 +102,9 @@ public class LoggerFactoryTests Assert.That(LoggerFactoryResolver.Provider, Is.InstanceOf()); } + /// + /// 测试LoggerFactoryResolver的Provider属性可以被更改 + /// [Test] public void LoggerFactoryResolver_Provider_CanBeChanged() { @@ -92,12 +118,18 @@ public class LoggerFactoryTests LoggerFactoryResolver.Provider = originalProvider; } + /// + /// 测试LoggerFactoryResolver的MinLevel属性是否有默认值 + /// [Test] public void LoggerFactoryResolver_MinLevel_ShouldHaveDefaultValue() { Assert.That(LoggerFactoryResolver.MinLevel, Is.EqualTo(LogLevel.Info)); } + /// + /// 测试LoggerFactoryResolver的MinLevel属性可以被更改 + /// [Test] public void LoggerFactoryResolver_MinLevel_CanBeChanged() { @@ -110,6 +142,9 @@ public class LoggerFactoryTests LoggerFactoryResolver.MinLevel = originalLevel; } + /// + /// 测试ConsoleLoggerFactoryProvider的MinLevel属性是否有默认值 + /// [Test] public void ConsoleLoggerFactoryProvider_MinLevel_ShouldHaveDefaultValue() { @@ -118,6 +153,9 @@ public class LoggerFactoryTests Assert.That(provider.MinLevel, Is.EqualTo(LogLevel.Info)); } + /// + /// 测试ConsoleLoggerFactoryProvider的MinLevel属性可以被更改 + /// [Test] public void ConsoleLoggerFactoryProvider_MinLevel_CanBeChanged() { @@ -128,6 +166,9 @@ public class LoggerFactoryTests Assert.That(provider.MinLevel, Is.EqualTo(LogLevel.Debug)); } + /// + /// 测试LoggerFactoryResolver的Provider创建logger时使用提供者设置 + /// [Test] public void LoggerFactoryResolver_Provider_CreateLogger_ShouldUseProviderSettings() { @@ -141,6 +182,7 @@ public class LoggerFactoryTests var stringWriter = new StringWriter(); var testLogger = new ConsoleLogger("TestLogger", LogLevel.Warning, stringWriter, false); + // 验证Warn消息会被记录,但Info消息不会被记录 testLogger.Warn("Warn message"); testLogger.Info("Info message"); @@ -151,6 +193,9 @@ public class LoggerFactoryTests LoggerFactoryResolver.Provider = originalProvider; } + /// + /// 测试LoggerFactoryResolver的MinLevel属性影响新创建的logger + /// [Test] public void LoggerFactoryResolver_MinLevel_AffectsNewLoggers() { @@ -164,6 +209,7 @@ public class LoggerFactoryTests var stringWriter = new StringWriter(); var testLogger = new ConsoleLogger("TestLogger", LogLevel.Error, stringWriter, false); + // 验证Error消息会被记录,但Warn消息不会被记录 testLogger.Error("Error message"); testLogger.Warn("Warn message"); @@ -174,6 +220,9 @@ public class LoggerFactoryTests LoggerFactoryResolver.MinLevel = originalMinLevel; } + /// + /// 测试ConsoleLoggerFactory创建的多个logger实例是独立的 + /// [Test] public void ConsoleLoggerFactory_MultipleLoggers_ShouldBeIndependent() { @@ -185,6 +234,9 @@ public class LoggerFactoryTests Assert.That(logger2.Name(), Is.EqualTo("Logger2")); } + /// + /// 测试ConsoleLoggerFactoryProvider的MinLevel不会影响已创建的logger + /// [Test] public void ConsoleLoggerFactoryProvider_MinLevel_DoesNotAffectCreatedLogger() { @@ -194,6 +246,7 @@ public class LoggerFactoryTests var stringWriter = new StringWriter(); var testLogger = new ConsoleLogger("TestLogger", LogLevel.Error, stringWriter, false); + // 验证Error和Fatal消息都会被记录 testLogger.Error("Error message"); testLogger.Fatal("Fatal message"); diff --git a/GFramework.Core.Tests/logging/LoggerTests.cs b/GFramework.Core.Tests/logging/LoggerTests.cs index 35aa49f..5e62625 100644 --- a/GFramework.Core.Tests/logging/LoggerTests.cs +++ b/GFramework.Core.Tests/logging/LoggerTests.cs @@ -4,9 +4,16 @@ using NUnit.Framework; namespace GFramework.Core.Tests.logging; +/// +/// 测试Logger功能的单元测试类 +/// [TestFixture] public class LoggerTests { + /// + /// 在每个测试方法执行前设置测试环境 + /// 创建一个新的TestLogger实例,名称为"TestLogger",最小日志级别为Info + /// [SetUp] public void SetUp() { @@ -15,6 +22,9 @@ public class LoggerTests private TestLogger _logger = null!; + /// + /// 验证Name方法是否正确返回Logger的名称 + /// [Test] public void Name_Should_ReturnLoggerName() { @@ -23,6 +33,9 @@ public class LoggerTests Assert.That(name, Is.EqualTo("TestLogger")); } + /// + /// 验证当使用默认名称时,Name方法是否返回根Logger名称"ROOT" + /// [Test] public void Name_WithDefaultName_Should_ReturnRootLoggerName() { @@ -31,42 +44,63 @@ public class LoggerTests Assert.That(defaultLogger.Name(), Is.EqualTo("ROOT")); } + /// + /// 验证当最小日志级别为Info时,IsTraceEnabled方法是否返回false + /// [Test] public void IsTraceEnabled_WithInfoMinLevel_Should_ReturnFalse() { Assert.That(_logger.IsTraceEnabled(), Is.False); } + /// + /// 验证当最小日志级别为Info时,IsDebugEnabled方法是否返回false + /// [Test] public void IsDebugEnabled_WithInfoMinLevel_Should_ReturnFalse() { Assert.That(_logger.IsDebugEnabled(), Is.False); } + /// + /// 验证当最小日志级别为Info时,IsInfoEnabled方法是否返回true + /// [Test] public void IsInfoEnabled_WithInfoMinLevel_Should_ReturnTrue() { Assert.That(_logger.IsInfoEnabled(), Is.True); } + /// + /// 验证当最小日志级别为Info时,IsWarnEnabled方法是否返回true + /// [Test] public void IsWarnEnabled_WithInfoMinLevel_Should_ReturnTrue() { Assert.That(_logger.IsWarnEnabled(), Is.True); } + /// + /// 验证当最小日志级别为Info时,IsErrorEnabled方法是否返回true + /// [Test] public void IsErrorEnabled_WithInfoMinLevel_Should_ReturnTrue() { Assert.That(_logger.IsErrorEnabled(), Is.True); } + /// + /// 验证当最小日志级别为Info时,IsFatalEnabled方法是否返回true + /// [Test] public void IsFatalEnabled_WithInfoMinLevel_Should_ReturnTrue() { Assert.That(_logger.IsFatalEnabled(), Is.True); } + /// + /// 验证IsEnabledForLevel方法对于不同日志级别的返回值是否正确 + /// [Test] public void IsEnabledForLevel_WithValidLevel_Should_ReturnCorrectResult() { @@ -78,12 +112,18 @@ public class LoggerTests Assert.That(_logger.IsEnabledForLevel(LogLevel.Fatal), Is.True); } + /// + /// 验证当传入无效的日志级别时,IsEnabledForLevel方法是否会抛出ArgumentException异常 + /// [Test] public void IsEnabledForLevel_WithInvalidLevel_Should_ThrowArgumentException() { Assert.Throws(() => { _logger.IsEnabledForLevel((LogLevel)999); }); } + /// + /// 验证当Trace级别被禁用时,Trace方法不会写入日志 + /// [Test] public void Trace_ShouldNotWrite_WhenTraceDisabled() { @@ -92,6 +132,9 @@ public class LoggerTests Assert.That(_logger.Logs.Count, Is.EqualTo(0)); } + /// + /// 验证当Trace级别被禁用时,带格式化参数的Trace方法不会写入日志 + /// [Test] public void Trace_WithFormat_ShouldNotWrite_WhenTraceDisabled() { @@ -100,6 +143,9 @@ public class LoggerTests Assert.That(_logger.Logs.Count, Is.EqualTo(0)); } + /// + /// 验证当Trace级别被禁用时,带两个参数的Trace方法不会写入日志 + /// [Test] public void Trace_WithTwoArgs_ShouldNotWrite_WhenTraceDisabled() { @@ -108,6 +154,9 @@ public class LoggerTests Assert.That(_logger.Logs.Count, Is.EqualTo(0)); } + /// + /// 验证当Trace级别被禁用时,带异常参数的Trace方法不会写入日志 + /// [Test] public void Trace_WithException_ShouldNotWrite_WhenTraceDisabled() { @@ -117,6 +166,9 @@ public class LoggerTests Assert.That(_logger.Logs.Count, Is.EqualTo(0)); } + /// + /// 验证当Debug级别被禁用时,Debug方法不会写入日志 + /// [Test] public void Debug_ShouldNotWrite_WhenDebugDisabled() { @@ -125,6 +177,9 @@ public class LoggerTests Assert.That(_logger.Logs.Count, Is.EqualTo(0)); } + /// + /// 验证当Debug级别被禁用时,带格式化参数的Debug方法不会写入日志 + /// [Test] public void Debug_WithFormat_ShouldNotWrite_WhenDebugDisabled() { @@ -133,6 +188,9 @@ public class LoggerTests Assert.That(_logger.Logs.Count, Is.EqualTo(0)); } + /// + /// 验证当Info级别启用时,Info方法会正确写入日志 + /// [Test] public void Info_ShouldWrite_WhenInfoEnabled() { @@ -144,6 +202,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Exception, Is.Null); } + /// + /// 验证带格式化参数的Info方法会正确写入格式化后的消息 + /// [Test] public void Info_WithFormat_ShouldWriteFormattedMessage() { @@ -153,6 +214,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Formatted message")); } + /// + /// 验证带两个参数的Info方法会正确写入格式化后的消息 + /// [Test] public void Info_WithTwoArgs_ShouldWriteFormattedMessage() { @@ -162,6 +226,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Formatted arg1 and arg2")); } + /// + /// 验证带多个参数的Info方法会正确写入格式化后的消息 + /// [Test] public void Info_WithMultipleArgs_ShouldWriteFormattedMessage() { @@ -171,6 +238,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Formatted arg1, arg2, arg3")); } + /// + /// 验证带异常参数的Info方法会正确写入消息和异常 + /// [Test] public void Info_WithException_ShouldWriteMessageAndException() { @@ -182,6 +252,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Exception, Is.SameAs(exception)); } + /// + /// 验证当Warn级别启用时,Warn方法会正确写入日志 + /// [Test] public void Warn_ShouldWrite_WhenWarnEnabled() { @@ -192,6 +265,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Warn message")); } + /// + /// 验证带格式化参数的Warn方法会正确写入格式化后的消息 + /// [Test] public void Warn_WithFormat_ShouldWriteFormattedMessage() { @@ -201,6 +277,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Formatted message")); } + /// + /// 验证带异常参数的Warn方法会正确写入消息和异常 + /// [Test] public void Warn_WithException_ShouldWriteMessageAndException() { @@ -211,6 +290,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Exception, Is.SameAs(exception)); } + /// + /// 验证当Error级别启用时,Error方法会正确写入日志 + /// [Test] public void Error_ShouldWrite_WhenErrorEnabled() { @@ -221,6 +303,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Error message")); } + /// + /// 验证带格式化参数的Error方法会正确写入格式化后的消息 + /// [Test] public void Error_WithFormat_ShouldWriteFormattedMessage() { @@ -230,6 +315,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Formatted message")); } + /// + /// 验证带异常参数的Error方法会正确写入消息和异常 + /// [Test] public void Error_WithException_ShouldWriteMessageAndException() { @@ -240,6 +328,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Exception, Is.SameAs(exception)); } + /// + /// 验证当Fatal级别启用时,Fatal方法会正确写入日志 + /// [Test] public void Fatal_ShouldWrite_WhenFatalEnabled() { @@ -250,6 +341,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Fatal message")); } + /// + /// 验证带格式化参数的Fatal方法会正确写入格式化后的消息 + /// [Test] public void Fatal_WithFormat_ShouldWriteFormattedMessage() { @@ -259,6 +353,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Message, Is.EqualTo("Formatted message")); } + /// + /// 验证带异常参数的Fatal方法会正确写入消息和异常 + /// [Test] public void Fatal_WithException_ShouldWriteMessageAndException() { @@ -269,6 +366,9 @@ public class LoggerTests Assert.That(_logger.Logs[0].Exception, Is.SameAs(exception)); } + /// + /// 验证多次调用日志方法会累积日志条目 + /// [Test] public void MultipleLogCalls_ShouldAccumulateLogs() { @@ -282,6 +382,9 @@ public class LoggerTests Assert.That(_logger.Logs[2].Message, Is.EqualTo("Message 3")); } + /// + /// 验证当最小日志级别设置为Trace时,所有级别的日志都会被启用 + /// [Test] public void Logger_WithTraceMinLevel_ShouldEnableAllLevels() { @@ -297,6 +400,9 @@ public class LoggerTests Assert.That(traceLogger.Logs.Count, Is.EqualTo(6)); } + /// + /// 验证当最小日志级别设置为Fatal时,只有Fatal级别的日志会被启用 + /// [Test] public void Logger_WithFatalMinLevel_ShouldDisableAllButFatal() { @@ -314,18 +420,41 @@ public class LoggerTests } } +/// +/// 测试用的日志记录器实现类,继承自AbstractLogger +/// public sealed class TestLogger : AbstractLogger { + /// + /// 初始化TestLogger的新实例 + /// + /// 日志记录器的名称,默认为null + /// 最小日志级别,默认为LogLevel.Info public TestLogger(string? name = null, LogLevel minLevel = LogLevel.Info) : base(name, minLevel) { } + /// + /// 获取记录的日志条目列表 + /// public List Logs { get; } = new(); + /// + /// 将日志信息写入内部存储 + /// + /// 日志级别 + /// 日志消息 + /// 相关异常(可选) protected override void Write(LogLevel level, string message, Exception? exception) { Logs.Add(new LogEntry(level, message, exception)); } + /// + /// 表示单个日志条目的记录类型 + /// + /// 日志级别 + /// 日志消息 + /// 相关异常(可选) public sealed record LogEntry(LogLevel Level, string Message, Exception? Exception); } \ No newline at end of file diff --git a/GFramework.Core.Tests/pool/ObjectPoolTests.cs b/GFramework.Core.Tests/pool/ObjectPoolTests.cs index 27c9449..ec262a2 100644 --- a/GFramework.Core.Tests/pool/ObjectPoolTests.cs +++ b/GFramework.Core.Tests/pool/ObjectPoolTests.cs @@ -4,17 +4,29 @@ using NUnit.Framework; namespace GFramework.Core.Tests.pool; +/// +/// 对象池功能测试类,用于验证对象池的基本操作和行为 +/// [TestFixture] public class ObjectPoolTests { + /// + /// 测试初始化方法,在每个测试方法执行前设置测试环境 + /// [SetUp] public void SetUp() { _pool = new TestObjectPool(); } + /// + /// 测试用的对象池实例 + /// private TestObjectPool _pool = null!; + /// + /// 验证当对象池为空时,Acquire方法应该创建新对象 + /// [Test] public void Acquire_Should_Create_New_Object_When_Pool_Empty() { @@ -25,6 +37,9 @@ public class ObjectPoolTests Assert.That(obj.OnAcquireCalled, Is.True); } + /// + /// 验证Acquire方法应该返回池中的可用对象 + /// [Test] public void Acquire_Should_Return_Pooled_Object() { @@ -40,6 +55,9 @@ public class ObjectPoolTests Assert.That(obj2.OnAcquireCalled, Is.True); } + /// + /// 验证Release方法应该调用对象的OnRelease回调 + /// [Test] public void Release_Should_Call_OnRelease() { @@ -50,6 +68,9 @@ public class ObjectPoolTests Assert.That(obj.OnReleaseCalled, Is.True); } + /// + /// 验证Clear方法应该销毁所有对象 + /// [Test] public void Clear_Should_Destroy_All_Objects() { @@ -65,6 +86,9 @@ public class ObjectPoolTests Assert.That(obj2.OnPoolDestroyCalled, Is.True); } + /// + /// 验证多个池键应该相互独立 + /// [Test] public void Multiple_Pools_Should_Be_Independent() { @@ -80,6 +104,9 @@ public class ObjectPoolTests Assert.That(obj4, Is.Not.SameAs(obj2)); } + /// + /// 验证OnAcquire回调应该在新对象和池中对象上都被调用 + /// [Test] public void OnAcquire_Should_Be_Called_On_New_And_Pooled_Objects() { @@ -94,36 +121,78 @@ public class ObjectPoolTests } } +/// +/// 测试用对象池实现类,继承自AbstractObjectPoolSystem +/// public class TestObjectPool : AbstractObjectPoolSystem { + /// + /// 创建新的池化对象 + /// + /// 用于标识对象的键 + /// 新创建的TestPoolableObject实例 protected override TestPoolableObject Create(string key) { return new TestPoolableObject { PoolKey = key }; } + /// + /// 初始化方法,用于对象池初始化时的操作 + /// protected override void OnInit() { } } +/// +/// 测试用池化对象类,实现了IPoolableObject接口 +/// public class TestPoolableObject : IPoolableObject { + /// + /// 获取或设置对象的池键 + /// public string PoolKey { get; set; } = string.Empty; + + /// + /// 获取或设置测试用的整数值 + /// public int TestValue { get; set; } + + /// + /// 获取或设置OnAcquire方法是否被调用的标志 + /// public bool OnAcquireCalled { get; set; } + + /// + /// 获取或设置OnRelease方法是否被调用的标志 + /// public bool OnReleaseCalled { get; set; } + + /// + /// 获取或设置OnPoolDestroy方法是否被调用的标志 + /// public bool OnPoolDestroyCalled { get; set; } + /// + /// 对象被获取时的回调方法 + /// public void OnAcquire() { OnAcquireCalled = true; } + /// + /// 对象被释放时的回调方法 + /// public void OnRelease() { OnReleaseCalled = true; } + /// + /// 对象被销毁时的回调方法 + /// public void OnPoolDestroy() { OnPoolDestroyCalled = true; diff --git a/GFramework.Core.Tests/property/BindablePropertyTests.cs b/GFramework.Core.Tests/property/BindablePropertyTests.cs index d3c8617..650a0e8 100644 --- a/GFramework.Core.Tests/property/BindablePropertyTests.cs +++ b/GFramework.Core.Tests/property/BindablePropertyTests.cs @@ -3,15 +3,24 @@ using NUnit.Framework; namespace GFramework.Core.Tests.property; +/// +/// BindableProperty类的单元测试 +/// [TestFixture] public class BindablePropertyTests { + /// + /// 测试清理方法,在每个测试方法执行后重置比较器 + /// [TearDown] public void TearDown() { BindableProperty.Comparer = (a, b) => a?.Equals(b) ?? b == null; } + /// + /// 测试获取值时应返回默认值 + /// [Test] public void Value_Get_Should_Return_Default_Value() { @@ -20,6 +29,9 @@ public class BindablePropertyTests Assert.That(property.Value, Is.EqualTo(5)); } + /// + /// 测试设置值时应触发事件 + /// [Test] public void Value_Set_Should_Trigger_Event() { @@ -33,6 +45,9 @@ public class BindablePropertyTests Assert.That(receivedValue, Is.EqualTo(42)); } + /// + /// 测试设置相同值时不触发事件 + /// [Test] public void Value_Set_To_Same_Value_Should_Not_Trigger_Event() { @@ -46,6 +61,9 @@ public class BindablePropertyTests Assert.That(count, Is.EqualTo(0)); } + /// + /// 测试取消注册应移除处理器 + /// [Test] public void UnRegister_Should_Remove_Handler() { @@ -63,6 +81,9 @@ public class BindablePropertyTests Assert.That(count, Is.EqualTo(1)); } + /// + /// 测试带初始值注册应立即调用处理器 + /// [Test] public void RegisterWithInitValue_Should_Call_Handler_Immediately() { @@ -74,6 +95,9 @@ public class BindablePropertyTests Assert.That(receivedValue, Is.EqualTo(5)); } + /// + /// 测试无事件设置值不应触发事件 + /// [Test] public void SetValueWithoutEvent_Should_Not_Trigger_Event() { @@ -88,12 +112,16 @@ public class BindablePropertyTests Assert.That(property.Value, Is.EqualTo(42)); } + /// + /// 测试使用自定义比较器 + /// [Test] public void WithComparer_Should_Use_Custom_Comparer() { var comparerWasCalled = false; var comparisonResult = false; + // 设置自定义比较器 BindableProperty.Comparer = (a, b) => { comparerWasCalled = true; @@ -112,6 +140,9 @@ public class BindablePropertyTests Assert.That(count, Is.EqualTo(0), "不应该触发事件"); } + /// + /// 测试多个处理器都应被调用 + /// [Test] public void Multiple_Handlers_Should_All_Be_Called() { @@ -128,6 +159,9 @@ public class BindablePropertyTests Assert.That(count2, Is.EqualTo(1)); } + /// + /// 测试注册应返回IUnRegister接口 + /// [Test] public void Register_Should_Return_IUnRegister() { @@ -137,6 +171,9 @@ public class BindablePropertyTests Assert.That(unRegister, Is.Not.Null); } + /// + /// 测试ToString应返回值的字符串表示 + /// [Test] public void ToString_Should_Return_Value_As_String() { diff --git a/GFramework.Core.Tests/query/QueryBusTests.cs b/GFramework.Core.Tests/query/QueryBusTests.cs index 2efa95a..89e9a62 100644 --- a/GFramework.Core.Tests/query/QueryBusTests.cs +++ b/GFramework.Core.Tests/query/QueryBusTests.cs @@ -4,9 +4,15 @@ using NUnit.Framework; namespace GFramework.Core.Tests.query; +/// +/// 查询总线测试类,用于测试QueryBus的功能和异常处理 +/// [TestFixture] public class QueryBusTests { + /// + /// 测试设置方法,在每个测试方法执行前初始化查询总线实例 + /// [SetUp] public void SetUp() { @@ -15,6 +21,10 @@ public class QueryBusTests private QueryBus _queryBus = null!; + /// + /// 测试Send方法是否能正确返回查询结果 + /// 验证当传入有效查询对象时,能够得到预期的计算结果 + /// [Test] public void Send_Should_Return_Query_Result() { @@ -26,12 +36,20 @@ public class QueryBusTests Assert.That(result, Is.EqualTo(20)); } + /// + /// 测试Send方法在传入空查询对象时是否会抛出ArgumentNullException异常 + /// 验证参数验证功能的正确性 + /// [Test] public void Send_WithNullQuery_Should_ThrowArgumentNullException() { Assert.Throws(() => _queryBus.Send(null!)); } + /// + /// 测试Send方法是否能正确返回字符串类型的查询结果 + /// 验证不同返回类型的支持情况 + /// [Test] public void Send_WithStringResult_Should_Return_String() { @@ -44,29 +62,62 @@ public class QueryBusTests } } +/// +/// 测试用查询输入类,实现IQueryInput接口 +/// 用于传递查询所需的参数信息 +/// public sealed class TestQueryInput : IQueryInput { + /// + /// 获取或设置查询值 + /// public int Value { get; init; } } +/// +/// 整数类型测试查询类,继承自AbstractQuery +/// 实现具体的查询逻辑并返回整数结果 +/// public sealed class TestQuery : AbstractQuery { + /// + /// 初始化TestQuery的新实例 + /// + /// 查询输入参数 public TestQuery(TestQueryInput input) : base(input) { } + /// + /// 执行查询操作的具体实现 + /// + /// 查询输入参数 + /// 查询结果,将输入值乘以2 protected override int OnDo(TestQueryInput input) { return input.Value * 2; } } +/// +/// 字符串类型测试查询类,继承自AbstractQuery +/// 实现具体的查询逻辑并返回字符串结果 +/// public sealed class TestStringQuery : AbstractQuery { + /// + /// 初始化TestStringQuery的新实例 + /// + /// 查询输入参数 public TestStringQuery(TestQueryInput input) : base(input) { } + /// + /// 执行查询操作的具体实现 + /// + /// 查询输入参数 + /// 格式化的字符串结果 protected override string OnDo(TestQueryInput input) { return $"Result: {input.Value * 2}"; diff --git a/GFramework.Core.Tests/rule/ContextAwareTests.cs b/GFramework.Core.Tests/rule/ContextAwareTests.cs index 70cbf6b..8aec9f1 100644 --- a/GFramework.Core.Tests/rule/ContextAwareTests.cs +++ b/GFramework.Core.Tests/rule/ContextAwareTests.cs @@ -7,9 +7,17 @@ using NUnit.Framework; namespace GFramework.Core.Tests.rule; +/// +/// 测试 ContextAware 功能的单元测试类 +/// 验证上下文感知对象的设置、获取和回调功能 +/// [TestFixture] public class ContextAwareTests { + /// + /// 在每个测试方法执行前进行初始化设置 + /// 创建测试用的 ContextAware 对象和模拟上下文,并绑定到游戏上下文中 + /// [SetUp] public void SetUp() { @@ -18,6 +26,10 @@ public class ContextAwareTests GameContext.Bind(typeof(TestArchitectureContext), _mockContext); } + /// + /// 在每个测试方法执行后进行清理工作 + /// 从游戏上下文中解绑测试用的架构上下文类型 + /// [TearDown] public void TearDown() { @@ -27,6 +39,10 @@ public class ContextAwareTests private TestContextAware _contextAware = null!; private TestArchitectureContext _mockContext = null!; + /// + /// 测试 SetContext 方法是否正确设置上下文属性 + /// 验证通过 IContextAware 接口设置上下文后,内部的 PublicContext 属性能够正确返回设置的上下文 + /// [Test] public void SetContext_Should_Set_Context_Property() { @@ -36,6 +52,10 @@ public class ContextAwareTests Assert.That(_contextAware.PublicContext, Is.SameAs(_mockContext)); } + /// + /// 测试 SetContext 方法是否正确调用 OnContextReady 回调方法 + /// 验证设置上下文后,OnContextReady 方法被正确触发 + /// [Test] public void SetContext_Should_Call_OnContextReady() { @@ -45,6 +65,10 @@ public class ContextAwareTests Assert.That(_contextAware.OnContextReadyCalled, Is.True); } + /// + /// 测试 GetContext 方法是否返回已设置的上下文 + /// 验证通过 IContextAware 接口设置上下文后,GetContext 方法能正确返回相同的上下文实例 + /// [Test] public void GetContext_Should_Return_Set_Context() { @@ -56,6 +80,11 @@ public class ContextAwareTests Assert.That(result, Is.SameAs(_mockContext)); } + /// + /// 测试 GetContext 方法在未设置上下文时的行为 + /// 验证当内部 Context 为 null 时,GetContext 方法不会抛出异常 + /// 此时应返回第一个架构上下文(在测试环境中验证不抛出异常即可) + /// [Test] public void GetContext_Should_Return_FirstArchitectureContext_When_Not_Set() { @@ -72,11 +101,26 @@ public class ContextAwareTests } } +/// +/// 用于测试的 ContextAware 实现类 +/// 继承自 ContextAwareBase,提供公共访问的上下文属性和回调状态跟踪 +/// public class TestContextAware : ContextAwareBase { + /// + /// 获取内部上下文的公共访问属性 + /// public IArchitectureContext? PublicContext => Context; + + /// + /// 跟踪 OnContextReady 方法是否被调用的状态 + /// public bool OnContextReadyCalled { get; private set; } + /// + /// 重写上下文就绪回调方法 + /// 设置 OnContextReadyCalled 标志为 true,用于测试验证 + /// protected override void OnContextReady() { OnContextReadyCalled = true; diff --git a/GFramework.Core.Tests/state/ContextAwareStateMachineTests.cs b/GFramework.Core.Tests/state/ContextAwareStateMachineTests.cs index 4a0acba..d52d71a 100644 --- a/GFramework.Core.Tests/state/ContextAwareStateMachineTests.cs +++ b/GFramework.Core.Tests/state/ContextAwareStateMachineTests.cs @@ -1,4 +1,3 @@ -using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.enums; using GFramework.Core.Abstractions.state; using GFramework.Core.Abstractions.system; @@ -13,13 +12,26 @@ using NUnit.Framework; namespace GFramework.Core.Tests.state; +/// +/// ContextAwareStateMachine类的单元测试 +/// 测试内容包括: +/// - 作为ISystem的集成测试 +/// - Init方法 - 初始化上下文感知状态 +/// - Init方法 - 设置Context属性 +/// - Destroy方法 - 清理状态 +/// - OnArchitecturePhase方法 - 接收架构阶段 +/// - 上下文感知状态初始化 +/// - 状态变更事件发送 +/// - SetContext方法 +/// - GetContext方法 +/// - ISystem接口实现验证 +/// - 与EventBus的集成测试 +/// - 多状态注册和切换 +/// - 状态机生命周期完整性 +/// [TestFixture] public class ContextAwareStateMachineTests { - private TestContextAwareStateMachineV5? _stateMachine; - private ArchitectureContext? _context; - private EventBus? _eventBus; - [SetUp] public void SetUp() { @@ -30,216 +42,312 @@ public class ContextAwareStateMachineTests new CommandBus(), new QueryBus(), new DefaultEnvironment()); - + _stateMachine = new TestContextAwareStateMachineV5(); _stateMachine.SetContext(_context); } + private TestContextAwareStateMachineV5? _stateMachine; + private ArchitectureContext? _context; + private EventBus? _eventBus; + + /// + /// 测试ContextAwareStateMachine实现ISystem接口 + /// [Test] public void ContextAwareStateMachine_Should_Implement_ISystem_Interface() { Assert.That(_stateMachine, Is.InstanceOf()); } + /// + /// 测试SetContext设置Context属性 + /// [Test] public void SetContext_Should_Set_Context_Property() { _stateMachine!.SetContext(_context!); - + var context = _stateMachine.GetContext(); Assert.That(context, Is.SameAs(_context)); } + /// + /// 测试GetContext返回Context属性 + /// [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)); } + /// + /// 测试Init方法为所有ContextAware状态设置Context + /// [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)); } + /// + /// 测试Init方法不为非ContextAware状态设置Context + /// [Test] public void Init_Should_Not_SetContext_On_NonContextAware_States() { var state = new TestStateV5(); - + _stateMachine!.Register(state); _stateMachine.Init(); } + /// + /// 测试Destroy方法不抛出异常 + /// [Test] public void Destroy_Should_Not_Throw_Exception() { Assert.That(() => _stateMachine!.Destroy(), Throws.Nothing); } + /// + /// 测试OnArchitecturePhase方法不抛出异常 + /// [Test] public void OnArchitecturePhase_Should_Not_Throw_Exception() { - Assert.That(() => _stateMachine!.OnArchitecturePhase(ArchitecturePhase.Ready), + Assert.That(() => _stateMachine!.OnArchitecturePhase(ArchitecturePhase.Ready), Throws.Nothing); } + /// + /// 测试ChangeTo发送StateChangedEvent事件 + /// 验证当状态机切换到新状态时,会正确触发StateChangedEvent事件,并且事件中的旧状态为null(首次切换) + /// [Test] public void ChangeTo_Should_Send_StateChangedEvent() { + // 订阅StateChangedEvent事件以验证事件是否被正确发送 bool eventReceived = false; StateChangedEvent? receivedEvent = null; - + _eventBus!.Register(e => { eventReceived = true; receivedEvent = e; }); - + var state1 = new TestStateV5(); var state2 = new TestStateV5(); - + _stateMachine!.Register(state1); _stateMachine.Register(state2); - + _stateMachine.Init(); _stateMachine.ChangeTo(); - + Assert.That(eventReceived, Is.True); Assert.That(receivedEvent!.OldState, Is.Null); Assert.That(receivedEvent.NewState, Is.InstanceOf()); } + /// + /// 测试ChangeTo发送StateChangedEvent事件(包含旧状态) + /// 验证当状态机从一个状态切换到另一个状态时,会正确触发StateChangedEvent事件, + /// 并且事件中包含正确的旧状态和新状态信息 + /// [Test] public void ChangeTo_Should_Send_StateChangedEvent_With_OldState() { + // 订阅StateChangedEvent事件以验证事件是否被正确发送 bool eventReceived = false; StateChangedEvent? receivedEvent = null; - + _eventBus!.Register(e => { eventReceived = true; receivedEvent = e; }); - + var state1 = new TestStateV5(); var state2 = new TestStateV5(); - + _stateMachine!.Register(state1); _stateMachine.Register(state2); - + _stateMachine.Init(); _stateMachine.ChangeTo(); _stateMachine.ChangeTo(); - + Assert.That(eventReceived, Is.True); Assert.That(receivedEvent!.OldState, Is.InstanceOf()); Assert.That(receivedEvent.NewState, Is.InstanceOf()); } + /// + /// 测试CanChangeTo方法对于已注册状态的工作情况 + /// 验证当状态已注册到状态机中时,CanChangeTo方法应返回true + /// [Test] public void CanChangeTo_Should_Work_With_Registered_States() { var state = new TestStateV5(); - + _stateMachine!.Register(state); - + var canChange = _stateMachine.CanChangeTo(); Assert.That(canChange, Is.True); } + /// + /// 测试可以注册多个状态 + /// 验证状态机能够成功注册多个不同的状态实例,并且能够切换到这些已注册的状态 + /// [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(); Assert.That(canChange, Is.True); } + + /// + /// 测试状态机生命周期完整 + /// [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(); Assert.That(_stateMachine.Current, Is.InstanceOf()); - + _stateMachine.Destroy(); } } #region Test Classes +/// +/// 测试用的ContextAwareStateMachine派生类,用于访问内部状态字典 +/// public class TestContextAwareStateMachineV5 : ContextAwareStateMachine { + /// + /// 获取状态机内部的状态字典 + /// + /// 类型到状态实例的映射字典 public Dictionary GetStates() => States; } +/// +/// 测试用的上下文感知状态基类实现 +/// public class TestContextAwareStateV5 : ContextAwareStateBase { + /// + /// 进入状态时调用 + /// + /// 前一个状态 public override void OnEnter(IState? previous) { } + /// + /// 退出状态时调用 + /// + /// 下一个状态 public override void OnExit(IState? next) { } } +/// +/// 第二个测试用的上下文感知状态基类实现 +/// public class TestContextAwareStateV5_2 : ContextAwareStateBase { + /// + /// 进入状态时调用 + /// + /// 前一个状态 public override void OnEnter(IState? previous) { } + /// + /// 退出状态时调用 + /// + /// 下一个状态 public override void OnExit(IState? next) { } } +/// +/// 测试用的普通状态实现 +/// public class TestStateV5 : IState { + /// + /// 状态标识符 + /// public int Id { get; set; } - + + /// + /// 检查是否可以转换到指定状态 + /// + /// 目标状态 + /// 始终返回true表示允许转换 public bool CanTransitionTo(IState next) => true; - + + /// + /// 进入状态时调用 + /// + /// 前一个状态 public void OnEnter(IState? previous) { } + /// + /// 退出状态时调用 + /// + /// 下一个状态 public void OnExit(IState? next) { } } -#endregion +#endregion \ No newline at end of file diff --git a/GFramework.Core.Tests/state/StateMachineTests.cs b/GFramework.Core.Tests/state/StateMachineTests.cs index db557b9..e47743c 100644 --- a/GFramework.Core.Tests/state/StateMachineTests.cs +++ b/GFramework.Core.Tests/state/StateMachineTests.cs @@ -1,12 +1,19 @@ +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() { @@ -15,12 +22,18 @@ public class StateMachineTests 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() { @@ -30,6 +43,9 @@ public class StateMachineTests Assert.That(_stateMachine.ContainsState(), Is.True); } + /// + /// 验证ChangeTo方法能够正确设置当前状态 + /// [Test] public void ChangeTo_Should_SetCurrentState() { @@ -40,6 +56,9 @@ public class StateMachineTests Assert.That(_stateMachine.Current, Is.SameAs(state)); } + /// + /// 验证ChangeTo方法会调用OnEnter回调 + /// [Test] public void ChangeTo_Should_Invoke_OnEnter() { @@ -51,6 +70,9 @@ public class StateMachineTests Assert.That(state.EnterFrom, Is.Null); } + /// + /// 验证当存在当前状态时,切换到新状态会调用原状态的OnExit回调 + /// [Test] public void ChangeTo_When_CurrentStateExists_Should_Invoke_OnExit() { @@ -66,6 +88,9 @@ public class StateMachineTests Assert.That(state1.ExitTo, Is.SameAs(state2)); } + /// + /// 验证当存在当前状态时,切换到新状态会调用新状态的OnEnter回调 + /// [Test] public void ChangeTo_When_CurrentStateExists_Should_Invoke_OnEnter() { @@ -81,6 +106,9 @@ public class StateMachineTests Assert.That(state2.EnterFrom, Is.SameAs(state1)); } + /// + /// 验证切换到相同状态时不应调用回调方法 + /// [Test] public void ChangeTo_ToSameState_Should_NotInvoke_Callbacks() { @@ -97,12 +125,18 @@ public class StateMachineTests 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() { @@ -110,6 +144,9 @@ public class StateMachineTests Assert.That(result, Is.False); } + /// + /// 验证当状态已注册时CanChangeTo方法应返回true + /// [Test] public void CanChangeTo_WhenStateRegistered_Should_ReturnTrue() { @@ -120,6 +157,9 @@ public class StateMachineTests Assert.That(result, Is.True); } + /// + /// 验证当当前状态拒绝转换时CanChangeTo方法应返回false + /// [Test] public void CanChangeTo_WhenCurrentStateDeniesTransition_Should_ReturnFalse() { @@ -133,6 +173,9 @@ public class StateMachineTests Assert.That(result, Is.False); } + /// + /// 验证当当前状态拒绝转换时不应发生状态变化 + /// [Test] public void ChangeTo_WhenCurrentStateDeniesTransition_Should_NotChange() { @@ -150,6 +193,9 @@ public class StateMachineTests Assert.That(state2.EnterCalled, Is.False); } + /// + /// 验证注销状态后应从字典中移除该状态 + /// [Test] public void Unregister_Should_RemoveState_FromDictionary() { @@ -160,6 +206,9 @@ public class StateMachineTests Assert.That(_stateMachine.ContainsState(), Is.False); } + /// + /// 验证当活动状态被注销时应调用OnExit并清除当前状态 + /// [Test] public void Unregister_WhenStateIsActive_Should_Invoke_OnExit_AndClearCurrent() { @@ -173,6 +222,9 @@ public class StateMachineTests Assert.That(_stateMachine.Current, Is.Null); } + /// + /// 验证当非活动状态被注销时不应调用OnExit + /// [Test] public void Unregister_WhenStateNotActive_Should_Not_Invoke_OnExit() { @@ -188,6 +240,9 @@ public class StateMachineTests Assert.That(_stateMachine.Current, Is.SameAs(state1)); } + /// + /// 验证多次状态转换应正确调用回调方法 + /// [Test] public void MultipleStateChanges_Should_Invoke_Callbacks_Correctly() { @@ -210,6 +265,9 @@ public class StateMachineTests Assert.That(state3.ExitCalled, Is.False); } + /// + /// 验证ChangeTo方法应遵循CanTransitionTo逻辑 + /// [Test] public void ChangeTo_Should_Respect_CanTransitionTo_Logic() { @@ -229,6 +287,9 @@ public class StateMachineTests } } +/// +/// 测试状态类V2版本,实现IState接口用于测试 +/// public sealed class TestStateV2 : IState { public bool AllowTransition { get; set; } = true; @@ -239,6 +300,10 @@ public sealed class TestStateV2 : IState public IState? EnterFrom { get; private set; } public IState? ExitTo { get; private set; } + /// + /// 进入状态时的回调方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; @@ -246,6 +311,10 @@ public sealed class TestStateV2 : IState EnterFrom = from; } + /// + /// 离开状态时的回调方法 + /// + /// 离开到哪个状态 public void OnExit(IState? to) { ExitCalled = true; @@ -253,12 +322,20 @@ public sealed class TestStateV2 : IState ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 是否允许转换 public bool CanTransitionTo(IState target) { return AllowTransition; } } +/// +/// 测试状态类V3版本,实现IState接口用于测试 +/// public sealed class TestStateV3 : IState { public bool EnterCalled { get; private set; } @@ -268,6 +345,10 @@ public sealed class TestStateV3 : IState public IState? EnterFrom { get; private set; } public IState? ExitTo { get; private set; } + /// + /// 进入状态时的回调方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; @@ -275,6 +356,10 @@ public sealed class TestStateV3 : IState EnterFrom = from; } + /// + /// 离开状态时的回调方法 + /// + /// 离开到哪个状态 public void OnExit(IState? to) { ExitCalled = true; @@ -282,12 +367,20 @@ public sealed class TestStateV3 : IState ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 是否允许转换 public bool CanTransitionTo(IState target) { return true; } } +/// +/// 测试状态类V4版本,实现IState接口用于测试 +/// public sealed class TestStateV4 : IState { public bool EnterCalled { get; private set; } @@ -297,6 +390,10 @@ public sealed class TestStateV4 : IState public IState? EnterFrom { get; private set; } public IState? ExitTo { get; private set; } + /// + /// 进入状态时的回调方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; @@ -304,6 +401,10 @@ public sealed class TestStateV4 : IState EnterFrom = from; } + /// + /// 离开状态时的回调方法 + /// + /// 离开到哪个状态 public void OnExit(IState? to) { ExitCalled = true; @@ -311,18 +412,32 @@ public sealed class TestStateV4 : IState 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", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)? - .GetValue(stateMachine) is System.Collections.Generic.Dictionary states && + return stateMachine.GetType().GetField("States", BindingFlags.NonPublic | BindingFlags.Instance)? + .GetValue(stateMachine) is Dictionary states && states.ContainsKey(typeof(T)); } -} +} \ No newline at end of file diff --git a/GFramework.Core.Tests/state/StateTests.cs b/GFramework.Core.Tests/state/StateTests.cs index dc07404..30db73c 100644 --- a/GFramework.Core.Tests/state/StateTests.cs +++ b/GFramework.Core.Tests/state/StateTests.cs @@ -1,12 +1,17 @@ using GFramework.Core.Abstractions.state; -using GFramework.Core.state; using NUnit.Framework; namespace GFramework.Core.Tests.state; +/// +/// 测试状态模式实现的功能和行为 +/// [TestFixture] public class StateTests { + /// + /// 验证状态类是否正确实现了IState接口 + /// [Test] public void State_Should_Implement_IState_Interface() { @@ -15,6 +20,9 @@ public class StateTests Assert.That(state is IState); } + /// + /// 验证进入状态时OnEnter方法被正确调用并记录来源状态 + /// [Test] public void OnEnter_Should_BeCalled_When_State_Enters() { @@ -27,6 +35,9 @@ public class StateTests Assert.That(state.EnterFrom, Is.SameAs(otherState)); } + /// + /// 验证当传入null作为来源状态时的处理情况 + /// [Test] public void OnEnter_WithNull_Should_Set_EnterFrom_ToNull() { @@ -38,6 +49,9 @@ public class StateTests Assert.That(state.EnterFrom, Is.Null); } + /// + /// 验证退出状态时OnExit方法被正确调用并记录目标状态 + /// [Test] public void OnExit_Should_BeCalled_When_State_Exits() { @@ -50,6 +64,9 @@ public class StateTests Assert.That(state.ExitTo, Is.SameAs(otherState)); } + /// + /// 验证当传入null作为目标状态时的处理情况 + /// [Test] public void OnExit_WithNull_Should_Set_ExitTo_ToNull() { @@ -61,6 +78,9 @@ public class StateTests Assert.That(state.ExitTo, Is.Null); } + /// + /// 验证允许转换时CanTransitionTo方法返回true + /// [Test] public void CanTransitionTo_WithAllowTrue_Should_ReturnTrue() { @@ -72,6 +92,9 @@ public class StateTests Assert.That(result, Is.True); } + /// + /// 验证不允许转换时CanTransitionTo方法返回false + /// [Test] public void CanTransitionTo_WithAllowFalse_Should_ReturnFalse() { @@ -83,6 +106,9 @@ public class StateTests Assert.That(result, Is.False); } + /// + /// 验证CanTransitionTo方法正确接收目标状态参数 + /// [Test] public void CanTransitionTo_Should_Receive_TargetState() { @@ -96,6 +122,9 @@ public class StateTests Assert.That(receivedTarget, Is.SameAs(target)); } + /// + /// 验证具有复杂转换规则的状态类功能 + /// [Test] public void State_WithComplexTransitionRules_Should_Work() { @@ -107,6 +136,9 @@ public class StateTests Assert.That(state1.CanTransitionTo(state3), Is.False); } + /// + /// 验证多个状态之间的协作功能 + /// [Test] public void MultipleStates_Should_WorkTogether() { @@ -126,6 +158,9 @@ public class StateTests Assert.That(state3.EnterFrom, Is.SameAs(state2)); } + /// + /// 验证状态对多次转换的跟踪能力 + /// [Test] public void State_Should_Track_MultipleTransitions() { @@ -141,6 +176,9 @@ public class StateTests Assert.That(state.ExitCallCount, Is.EqualTo(2)); } + /// + /// 验证相同类型状态间的转换处理 + /// [Test] public void State_Should_Handle_SameState_Transition() { @@ -158,27 +196,66 @@ public class StateTests } } +/// +/// 具体状态实现类V2版本,用于测试状态的基本功能 +/// public sealed class ConcreteStateV2 : IState { + /// + /// 获取或设置是否允许转换 + /// public bool AllowTransitions { get; set; } = true; + + /// + /// 获取进入状态是否被调用的标志 + /// public bool EnterCalled { get; private set; } + + /// + /// 获取退出状态是否被调用的标志 + /// public bool ExitCalled { get; private set; } + + /// + /// 获取进入此状态的来源状态 + /// public IState? EnterFrom { get; private set; } + + /// + /// 获取从此状态退出的目标状态 + /// public IState? ExitTo { get; private set; } + + /// + /// 获取或设置转换到目标状态时执行的动作 + /// public Action? CanTransitionToAction { get; set; } + /// + /// 进入当前状态时调用的方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterFrom = from; } + /// + /// 退出当前状态时调用的方法 + /// + /// 退出到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 如果可以转换则返回true,否则返回false public bool CanTransitionTo(IState target) { CanTransitionToAction?.Invoke(target); @@ -186,103 +263,231 @@ public sealed class ConcreteStateV2 : IState } } +/// +/// 具体状态实现类V3版本,用于测试状态的基本功能 +/// public sealed class ConcreteStateV3 : IState { + /// + /// 获取进入状态是否被调用的标志 + /// public bool EnterCalled { get; private set; } + + /// + /// 获取退出状态是否被调用的标志 + /// public bool ExitCalled { get; private set; } + + /// + /// 获取进入此状态的来源状态 + /// public IState? EnterFrom { get; private set; } + + /// + /// 获取从此状态退出的目标状态 + /// public IState? ExitTo { get; private set; } + /// + /// 进入当前状态时调用的方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterFrom = from; } + /// + /// 退出当前状态时调用的方法 + /// + /// 退出到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 如果可以转换则返回true,否则返回false public bool CanTransitionTo(IState target) { return true; } } +/// +/// 具体状态实现类V4版本,用于测试状态的基本功能 +/// public sealed class ConcreteStateV4 : IState { + /// + /// 获取进入状态是否被调用的标志 + /// public bool EnterCalled { get; private set; } + + /// + /// 获取退出状态是否被调用的标志 + /// public bool ExitCalled { get; private set; } + + /// + /// 获取进入此状态的来源状态 + /// public IState? EnterFrom { get; private set; } + + /// + /// 获取从此状态退出的目标状态 + /// public IState? ExitTo { get; private set; } + /// + /// 进入当前状态时调用的方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterFrom = from; } + /// + /// 退出当前状态时调用的方法 + /// + /// 退出到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 如果可以转换则返回true,否则返回false public bool CanTransitionTo(IState target) { return true; } } +/// +/// 条件状态实现类V2版本,支持基于类型的条件转换规则 +/// public sealed class ConditionalStateV2 : IState { + /// + /// 获取或设置允许转换到的状态类型数组 + /// public Type[] AllowedTransitions { get; set; } = Array.Empty(); + + /// + /// 获取进入状态是否被调用的标志 + /// public bool EnterCalled { get; private set; } + + /// + /// 获取退出状态是否被调用的标志 + /// public bool ExitCalled { get; private set; } + + /// + /// 获取进入此状态的来源状态 + /// public IState? EnterFrom { get; private set; } + + /// + /// 获取从此状态退出的目标状态 + /// public IState? ExitTo { get; private set; } + /// + /// 进入当前状态时调用的方法 + /// + /// 从哪个状态进入 public void OnEnter(IState? from) { EnterCalled = true; EnterFrom = from; } + /// + /// 退出当前状态时调用的方法 + /// + /// 退出到哪个状态 public void OnExit(IState? to) { ExitCalled = true; ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 如果目标状态类型在允许列表中则返回true,否则返回false public bool CanTransitionTo(IState target) { return AllowedTransitions.Contains(target.GetType()); } } +/// +/// 跟踪状态实现类V2版本,用于跟踪状态转换次数 +/// public sealed class TrackingStateV2 : IState { + /// + /// 获取进入状态被调用的次数 + /// 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) { EnterCallCount++; EnterFrom = from; } + /// + /// 退出当前状态时调用的方法 + /// + /// 退出到哪个状态 public void OnExit(IState? to) { ExitCallCount++; ExitTo = to; } + /// + /// 判断是否可以转换到目标状态 + /// + /// 目标状态 + /// 总是返回true public bool CanTransitionTo(IState target) { return true; } -} +} \ No newline at end of file