diff --git a/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotification.cs b/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotification.cs new file mode 100644 index 00000000..c9d8b478 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotification.cs @@ -0,0 +1,8 @@ +using GFramework.Cqrs.Abstractions.Cqrs; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 用于验证额外程序集接入是否成功的测试通知。 +/// +public sealed record AdditionalAssemblyNotification : INotification; diff --git a/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotificationHandlerRegistry.cs b/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotificationHandlerRegistry.cs new file mode 100644 index 00000000..de430148 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotificationHandlerRegistry.cs @@ -0,0 +1,46 @@ +using GFramework.Core.Abstractions.Logging; +using GFramework.Cqrs; +using GFramework.Cqrs.Abstractions.Cqrs; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 模拟由 source-generator 为扩展程序集生成的 CQRS handler registry。 +/// +internal sealed class AdditionalAssemblyNotificationHandlerRegistry : ICqrsHandlerRegistry +{ + /// + /// 将扩展程序集中的通知处理器映射写入服务集合。 + /// + /// 目标服务集合。 + /// 日志记录器。 + /// + /// 当 时抛出。 + /// + public void Register(IServiceCollection services, ILogger logger) + { + ArgumentNullException.ThrowIfNull(services); + ArgumentNullException.ThrowIfNull(logger); + + services.AddTransient>(_ => CreateHandler()); + logger.Debug( + $"Registered CQRS handler proxy for {typeof(INotificationHandler).FullName}."); + } + + /// + /// 创建一个仅供显式程序集注册路径使用的动态通知处理器。 + /// + /// 用于记录通知触发次数的测试替身处理器。 + private static INotificationHandler CreateHandler() + { + var handler = new Mock>(); + handler + .Setup(target => target.Handle(It.IsAny(), It.IsAny())) + .Returns(() => + { + AdditionalAssemblyNotificationHandlerState.RecordInvocation(); + return ValueTask.CompletedTask; + }); + return handler.Object; + } +} diff --git a/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotificationHandlerState.cs b/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotificationHandlerState.cs new file mode 100644 index 00000000..4718a77f --- /dev/null +++ b/GFramework.Core.Tests/Architectures/AdditionalAssemblyNotificationHandlerState.cs @@ -0,0 +1,33 @@ +namespace GFramework.Core.Tests.Architectures; + +/// +/// 记录模拟扩展程序集通知处理器的执行次数。 +/// +public static class AdditionalAssemblyNotificationHandlerState +{ + private static int _invocationCount; + + /// + /// 获取当前测试进程中该处理器的执行次数。 + /// + /// + /// 该计数器通过原子读写维护,以支持 NUnit 并行执行环境中的并发访问。 + /// + public static int InvocationCount => Volatile.Read(ref _invocationCount); + + /// + /// 记录一次通知处理,供测试断言显式程序集接入后的运行时行为。 + /// + public static void RecordInvocation() + { + Interlocked.Increment(ref _invocationCount); + } + + /// + /// 清理共享计数器,避免测试间相互污染。 + /// + public static void Reset() + { + Interlocked.Exchange(ref _invocationCount, 0); + } +} diff --git a/GFramework.Core.Tests/Architectures/ArchitectureAdditionalCqrsHandlersTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureAdditionalCqrsHandlersTests.cs index f191863d..fe2e50a5 100644 --- a/GFramework.Core.Tests/Architectures/ArchitectureAdditionalCqrsHandlersTests.cs +++ b/GFramework.Core.Tests/Architectures/ArchitectureAdditionalCqrsHandlersTests.cs @@ -121,88 +121,3 @@ public sealed class ArchitectureAdditionalCqrsHandlersTests return architecture; } } - -/// -/// 用于验证额外程序集接入是否成功的测试通知。 -/// -public sealed record AdditionalAssemblyNotification : INotification; - -/// -/// 记录模拟扩展程序集通知处理器的执行次数。 -/// -public static class AdditionalAssemblyNotificationHandlerState -{ - private static int _invocationCount; - - /// - /// 获取当前测试进程中该处理器的执行次数。 - /// - /// - /// 该计数器通过原子读写维护,以支持 NUnit 并行执行环境中的并发访问。 - /// - public static int InvocationCount => Volatile.Read(ref _invocationCount); - - /// - /// 记录一次通知处理,供测试断言显式程序集接入后的运行时行为。 - /// - public static void RecordInvocation() - { - Interlocked.Increment(ref _invocationCount); - } - - /// - /// 清理共享计数器,避免测试间相互污染。 - /// - public static void Reset() - { - Interlocked.Exchange(ref _invocationCount, 0); - } -} - -/// -/// 模拟由 source-generator 为扩展程序集生成的 CQRS handler registry。 -/// -internal sealed class AdditionalAssemblyNotificationHandlerRegistry : ICqrsHandlerRegistry -{ - /// - /// 将扩展程序集中的通知处理器映射写入服务集合。 - /// - /// 目标服务集合。 - /// 日志记录器。 - /// - /// 当 时抛出。 - /// - public void Register(IServiceCollection services, ILogger logger) - { - if (services is null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (logger is null) - { - throw new ArgumentNullException(nameof(logger)); - } - - services.AddTransient>(_ => CreateHandler()); - logger.Debug( - $"Registered CQRS handler proxy for {typeof(INotificationHandler).FullName}."); - } - - /// - /// 创建一个仅供显式程序集注册路径使用的动态通知处理器。 - /// - /// 用于记录通知触发次数的测试替身处理器。 - private static INotificationHandler CreateHandler() - { - var handler = new Mock>(); - handler - .Setup(target => target.Handle(It.IsAny(), It.IsAny())) - .Returns(() => - { - AdditionalAssemblyNotificationHandlerState.RecordInvocation(); - return ValueTask.CompletedTask; - }); - return handler.Object; - } -} diff --git a/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs index 685655a5..e0f204c7 100644 --- a/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs +++ b/GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs @@ -1,14 +1,10 @@ using System.Reflection; using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Command; -using GFramework.Core.Abstractions.Enums; using GFramework.Core.Abstractions.Environment; using GFramework.Core.Abstractions.Ioc; using GFramework.Core.Abstractions.Logging; -using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Query; -using GFramework.Core.Abstractions.Systems; -using GFramework.Core.Abstractions.Utility; using GFramework.Core.Architectures; using GFramework.Core.Command; using GFramework.Core.Environment; @@ -373,147 +369,3 @@ public class ArchitectureContextTests { } } - -#region Test Classes - -public class TestSystemV2 : ISystem -{ - private IArchitectureContext _context = null!; - public int Id { get; init; } - - public void SetContext(IArchitectureContext context) - { - _context = context; - } - - public IArchitectureContext GetContext() - { - return _context; - } - - public void Initialize() - { - } - - 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() - { - return _context; - } - - public void Initialize() - { - } - - 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() - { - return _context; - } -} - -public class TestQueryV2 : IQuery -{ - private IArchitectureContext _context = null!; - public int Result { get; init; } - - public int Do() - { - return Result; - } - - public void SetContext(IArchitectureContext context) - { - _context = context; - } - - public IArchitectureContext GetContext() - { - return _context; - } -} - -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() - { - return _context; - } -} - -public class TestCommandWithResultV2 : ICommand -{ - private IArchitectureContext _context = null!; - public int Result { get; init; } - - public int Execute() - { - return Result; - } - - public void SetContext(IArchitectureContext context) - { - _context = context; - } - - public IArchitectureContext GetContext() - { - return _context; - } -} - -public class TestEventV2 -{ - public int Data { get; init; } -} - -#endregion diff --git a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs index dff3af2c..a879804c 100644 --- a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs +++ b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs @@ -3,7 +3,6 @@ using GFramework.Core.Abstractions.Logging; using GFramework.Core.Abstractions.Utility; using GFramework.Core.Architectures; using GFramework.Core.Logging; -using GFramework.Cqrs.Abstractions.Cqrs; namespace GFramework.Core.Tests.Architectures; @@ -126,56 +125,3 @@ public class ArchitectureModulesBehaviorTests { } } - -/// -/// 用于验证管道行为注册是否生效的测试请求。 -/// -public sealed class ModuleBehaviorRequest : IRequest -{ -} - -/// -/// 处理测试请求的处理器。 -/// -public sealed class ModuleBehaviorRequestHandler : IRequestHandler -{ - /// - /// 返回固定结果,便于聚焦验证管道行为是否执行。 - /// - /// 请求实例。 - /// 取消令牌。 - /// 固定响应内容。 - public ValueTask Handle(ModuleBehaviorRequest request, CancellationToken cancellationToken) - { - return ValueTask.FromResult("handled"); - } -} - -/// -/// 记录请求通过管道次数的测试行为。 -/// -/// 请求类型。 -/// 响应类型。 -public sealed class TrackingPipelineBehavior : IPipelineBehavior - where TRequest : IRequest -{ - /// - /// 获取当前测试进程中该请求类型对应的行为触发次数。 - /// - public static int InvocationCount { get; set; } - - /// - /// 记录一次行为执行,然后继续执行下一个处理器。 - /// - /// 当前请求消息。 - /// 下一个处理委托。 - /// 取消令牌。 - /// 下游处理器的响应结果。 - public async ValueTask Handle( - TRequest message, MessageHandlerDelegate next, - CancellationToken cancellationToken) - { - InvocationCount++; - return await next(message, cancellationToken).ConfigureAwait(false); - } -} diff --git a/GFramework.Core.Tests/Architectures/ModuleBehaviorRequest.cs b/GFramework.Core.Tests/Architectures/ModuleBehaviorRequest.cs new file mode 100644 index 00000000..4d405b10 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/ModuleBehaviorRequest.cs @@ -0,0 +1,10 @@ +using GFramework.Cqrs.Abstractions.Cqrs; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 用于验证管道行为注册是否生效的测试请求。 +/// +public sealed class ModuleBehaviorRequest : IRequest +{ +} diff --git a/GFramework.Core.Tests/Architectures/ModuleBehaviorRequestHandler.cs b/GFramework.Core.Tests/Architectures/ModuleBehaviorRequestHandler.cs new file mode 100644 index 00000000..8bbf0f17 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/ModuleBehaviorRequestHandler.cs @@ -0,0 +1,20 @@ +using GFramework.Cqrs.Abstractions.Cqrs; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 处理测试请求的处理器。 +/// +public sealed class ModuleBehaviorRequestHandler : IRequestHandler +{ + /// + /// 返回固定结果,便于聚焦验证管道行为是否执行。 + /// + /// 请求实例。 + /// 取消令牌。 + /// 固定响应内容。 + public ValueTask Handle(ModuleBehaviorRequest request, CancellationToken cancellationToken) + { + return ValueTask.FromResult("handled"); + } +} diff --git a/GFramework.Core.Tests/Architectures/TestCommandV2.cs b/GFramework.Core.Tests/Architectures/TestCommandV2.cs new file mode 100644 index 00000000..d430cff1 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestCommandV2.cs @@ -0,0 +1,43 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Command; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的测试命令桩。 +/// +public sealed 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() + { + return _context; + } +} diff --git a/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs b/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs new file mode 100644 index 00000000..571ab4d9 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs @@ -0,0 +1,44 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Command; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的带返回值测试命令桩。 +/// +public sealed class TestCommandWithResultV2 : ICommand +{ + private IArchitectureContext _context = null!; + + /// + /// 获取命令执行结果;该值只能在对象初始化阶段设置。 + /// + public int Result { get; init; } + + /// + /// 执行测试命令并返回预设结果。 + /// + /// 测试预设的命令结果。 + public int Execute() + { + return Result; + } + + /// + /// 关联当前命令所属的架构上下文。 + /// + /// 要保存的架构上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前命令已绑定的架构上下文。 + /// + /// 测试期间保存的架构上下文。 + public IArchitectureContext GetContext() + { + return _context; + } +} diff --git a/GFramework.Core.Tests/Architectures/TestEventV2.cs b/GFramework.Core.Tests/Architectures/TestEventV2.cs new file mode 100644 index 00000000..38faf9b1 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestEventV2.cs @@ -0,0 +1,12 @@ +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的测试事件载荷。 +/// +public sealed class TestEventV2 +{ + /// + /// 获取或设置测试事件数据。 + /// + public int Data { get; init; } +} diff --git a/GFramework.Core.Tests/Architectures/TestModelV2.cs b/GFramework.Core.Tests/Architectures/TestModelV2.cs new file mode 100644 index 00000000..bc636a6d --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestModelV2.cs @@ -0,0 +1,58 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Enums; +using GFramework.Core.Abstractions.Model; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的测试模型桩。 +/// +public sealed class TestModelV2 : IModel +{ + private IArchitectureContext _context = null!; + + /// + /// 获取或设置测试用标识。 + /// + public int Id { get; init; } + + /// + /// 关联当前模型所属的架构上下文。 + /// + /// 要保存的架构上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前模型已绑定的架构上下文。 + /// + /// 测试期间保存的架构上下文。 + public IArchitectureContext GetContext() + { + return _context; + } + + /// + /// 初始化测试模型。 + /// + public void Initialize() + { + } + + /// + /// 接收架构阶段切换通知。 + /// + /// 当前架构阶段。 + public void OnArchitecturePhase(ArchitecturePhase phase) + { + } + + /// + /// 销毁测试模型。 + /// + public void Destroy() + { + } +} diff --git a/GFramework.Core.Tests/Architectures/TestQueryV2.cs b/GFramework.Core.Tests/Architectures/TestQueryV2.cs new file mode 100644 index 00000000..f95c2300 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestQueryV2.cs @@ -0,0 +1,44 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Query; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的测试查询桩。 +/// +public sealed class TestQueryV2 : IQuery +{ + private IArchitectureContext _context = null!; + + /// + /// 获取查询返回值;该值只能在对象初始化阶段设置。 + /// + public int Result { get; init; } + + /// + /// 执行查询并返回预设结果。 + /// + /// 测试预设的查询结果。 + public int Do() + { + return Result; + } + + /// + /// 关联当前查询所属的架构上下文。 + /// + /// 要保存的架构上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前查询已绑定的架构上下文。 + /// + /// 测试期间保存的架构上下文。 + public IArchitectureContext GetContext() + { + return _context; + } +} diff --git a/GFramework.Core.Tests/Architectures/TestSystemV2.cs b/GFramework.Core.Tests/Architectures/TestSystemV2.cs new file mode 100644 index 00000000..0d8be394 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestSystemV2.cs @@ -0,0 +1,58 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Enums; +using GFramework.Core.Abstractions.Systems; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的测试系统桩。 +/// +public sealed class TestSystemV2 : ISystem +{ + private IArchitectureContext _context = null!; + + /// + /// 获取或设置测试用标识。 + /// + public int Id { get; init; } + + /// + /// 关联当前系统所属的架构上下文。 + /// + /// 要保存的架构上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前系统已绑定的架构上下文。 + /// + /// 测试期间保存的架构上下文。 + public IArchitectureContext GetContext() + { + return _context; + } + + /// + /// 初始化测试系统。 + /// + public void Initialize() + { + } + + /// + /// 销毁测试系统。 + /// + public void Destroy() + { + } + + /// + /// 接收架构阶段切换通知。 + /// + /// 当前架构阶段。 + public void OnArchitecturePhase(ArchitecturePhase phase) + { + } +} diff --git a/GFramework.Core.Tests/Architectures/TestUtilityV2.cs b/GFramework.Core.Tests/Architectures/TestUtilityV2.cs new file mode 100644 index 00000000..c29b8307 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TestUtilityV2.cs @@ -0,0 +1,35 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Utility; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 为 提供的测试工具桩。 +/// +public sealed class TestUtilityV2 : IUtility +{ + private IArchitectureContext _context = null!; + + /// + /// 获取或设置测试用标识。 + /// + public int Id { get; init; } + + /// + /// 关联当前工具所属的架构上下文。 + /// + /// 要保存的架构上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前工具已绑定的架构上下文。 + /// + /// 测试期间保存的架构上下文。 + public IArchitectureContext GetContext() + { + return _context; + } +} diff --git a/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs b/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs new file mode 100644 index 00000000..a9148e96 --- /dev/null +++ b/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs @@ -0,0 +1,41 @@ +using System.Threading; +using GFramework.Cqrs.Abstractions.Cqrs; + +namespace GFramework.Core.Tests.Architectures; + +/// +/// 记录请求通过管道次数的测试行为。 +/// +/// 请求类型。 +/// 响应类型。 +public sealed class TrackingPipelineBehavior : IPipelineBehavior + where TRequest : IRequest +{ + private static int _invocationCount; + + /// + /// 获取当前测试进程中该请求类型对应的行为触发次数。 + /// 该计数器是按泛型闭包共享的静态状态,测试需要在每次运行前显式重置。 + /// + public static int InvocationCount + { + get => Volatile.Read(ref _invocationCount); + set => Volatile.Write(ref _invocationCount, value); + } + + /// + /// 以线程安全方式记录一次行为执行,然后继续执行下一个处理器。 + /// + /// 当前请求消息。 + /// 下一个处理委托。 + /// 取消令牌。 + /// 下游处理器的响应结果。 + public async ValueTask Handle( + TRequest message, + MessageHandlerDelegate next, + CancellationToken cancellationToken) + { + Interlocked.Increment(ref _invocationCount); + return await next(message, cancellationToken).ConfigureAwait(false); + } +} diff --git a/GFramework.Core.Tests/Command/AbstractAsyncCommandTests.cs b/GFramework.Core.Tests/Command/AbstractAsyncCommandTests.cs index 5c02898b..f4665286 100644 --- a/GFramework.Core.Tests/Command/AbstractAsyncCommandTests.cs +++ b/GFramework.Core.Tests/Command/AbstractAsyncCommandTests.cs @@ -229,171 +229,3 @@ public class AbstractAsyncCommandTests Assert.That(result, Is.EqualTo(200)); } } - -/// -/// 测试用命令输入类V2 -/// -public sealed class TestCommandInputV2 : ICommandInput -{ - /// - /// 获取或设置值 - /// - public int Value { get; init; } -} - -/// -/// 测试用异步命令类V3(无返回值) -/// -public sealed class TestAsyncCommandV3 : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommandV3(TestCommandInputV2 input) : base(input) - { - } - - /// - /// 获取命令是否已执行 - /// - public bool Executed { get; private set; } - - /// - /// 获取执行的值 - /// - public int ExecutedValue { get; private set; } - - /// - /// 执行异步命令的重写方法 - /// - /// 命令输入 - /// 表示异步操作的任务 - protected override Task OnExecuteAsync(TestCommandInputV2 input) - { - Executed = true; - ExecutedValue = input.Value; - return Task.CompletedTask; - } -} - -/// -/// 测试用异步命令类V3(有返回值) -/// -public sealed class TestAsyncCommandWithResultV3 : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommandWithResultV3(TestCommandInputV2 input) : base(input) - { - } - - /// - /// 获取命令是否已执行 - /// - public bool Executed { get; private set; } - - /// - /// 执行异步命令并返回结果的重写方法 - /// - /// 命令输入 - /// 执行结果的异步任务 - protected override Task OnExecuteAsync(TestCommandInputV2 input) - { - Executed = true; - return Task.FromResult(input.Value * 2); - } -} - -/// -/// 测试用异步命令类(抛出异常) -/// -public sealed class TestAsyncCommandWithExceptionV3 : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommandWithExceptionV3(TestCommandInputV2 input) : base(input) - { - } - - /// - /// 执行异步命令并抛出异常的重写方法 - /// - /// 命令输入 - /// 表示异步操作的任务 - /// 总是抛出异常 - protected override Task OnExecuteAsync(TestCommandInputV2 input) - { - throw new InvalidOperationException("Test exception"); - } -} - -/// -/// 测试用异步命令子类(无返回值) -/// -public sealed class TestAsyncCommandChildV3 : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommandChildV3(TestCommandInputV2 input) : base(input) - { - } - - /// - /// 获取命令是否已执行 - /// - public bool Executed { get; private set; } - - /// - /// 获取执行的值 - /// - public int ExecutedValue { get; private set; } - - /// - /// 执行异步命令的重写方法(子类实现) - /// - /// 命令输入 - /// 表示异步操作的任务 - protected override Task OnExecuteAsync(TestCommandInputV2 input) - { - Executed = true; - ExecutedValue = input.Value * 2; - return Task.CompletedTask; - } -} - -/// -/// 测试用异步命令子类(有返回值) -/// -public sealed class TestAsyncCommandWithResultChildV3 : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommandWithResultChildV3(TestCommandInputV2 input) : base(input) - { - } - - /// - /// 获取命令是否已执行 - /// - public bool Executed { get; private set; } - - /// - /// 执行异步命令并返回结果的重写方法(子类实现) - /// - /// 命令输入 - /// 执行结果的异步任务 - protected override Task OnExecuteAsync(TestCommandInputV2 input) - { - Executed = true; - return Task.FromResult(input.Value * 3); - } -} diff --git a/GFramework.Core.Tests/Command/CommandExecutorTests.cs b/GFramework.Core.Tests/Command/CommandExecutorTests.cs index f12130ad..1e684e11 100644 --- a/GFramework.Core.Tests/Command/CommandExecutorTests.cs +++ b/GFramework.Core.Tests/Command/CommandExecutorTests.cs @@ -1,5 +1,4 @@ using GFramework.Core.Command; -using GFramework.Cqrs.Abstractions.Cqrs.Command; namespace GFramework.Core.Tests.Command; @@ -121,144 +120,3 @@ public class CommandExecutorTests Assert.ThrowsAsync(() => _commandExecutor.SendAsync(null!)); } } - -/// -/// 测试用命令输入类,实现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; - ExecutedValue = 42; - } -} - -/// -/// 测试用带返回值的命令类,继承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; - return input.Value * 2; - } -} - -/// -/// 测试用异步命令类,继承AbstractAsyncCommand -/// -public sealed class TestAsyncCommand : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommand(TestCommandInput input) : base(input) - { - } - - /// - /// 获取命令是否已执行 - /// - public bool Executed { get; private set; } - - /// - /// 获取执行的值 - /// - public int ExecutedValue { get; private set; } - - /// - /// 执行异步命令的重写方法 - /// - /// 命令输入 - /// 表示异步操作的任务 - protected override Task OnExecuteAsync(TestCommandInput input) - { - Executed = true; - ExecutedValue = 42; - return Task.CompletedTask; - } -} - -/// -/// 测试用带返回值的异步命令类,继承AbstractAsyncCommand -/// -public sealed class TestAsyncCommandWithResult : AbstractAsyncCommand -{ - /// - /// 构造函数 - /// - /// 命令输入 - public TestAsyncCommandWithResult(TestCommandInput input) : base(input) - { - } - - /// - /// 获取命令是否已执行 - /// - public bool Executed { get; private set; } - - /// - /// 执行异步命令并返回结果的重写方法 - /// - /// 命令输入 - /// 执行结果的异步任务 - protected override Task OnExecuteAsync(TestCommandInput input) - { - Executed = true; - return Task.FromResult(input.Value * 2); - } -} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommand.cs b/GFramework.Core.Tests/Command/TestAsyncCommand.cs new file mode 100644 index 00000000..34be2a9c --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommand.cs @@ -0,0 +1,39 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的异步测试命令。 +/// +public sealed class TestAsyncCommand : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommand(TestCommandInput input) : base(input) + { + } + + /// + /// 获取一个值,该值指示命令是否已经执行。 + /// + public bool Executed { get; private set; } + + /// + /// 获取命令记录的执行结果值。 + /// + public int ExecutedValue { get; private set; } + + /// + /// 执行异步测试命令并记录执行状态。 + /// + /// 命令输入。 + /// 已完成的异步任务。 + protected override Task OnExecuteAsync(TestCommandInput input) + { + Executed = true; + ExecutedValue = 42; + return Task.CompletedTask; + } +} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommandChildV3.cs b/GFramework.Core.Tests/Command/TestAsyncCommandChildV3.cs new file mode 100644 index 00000000..d31d546e --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommandChildV3.cs @@ -0,0 +1,39 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的子类化无返回值异步测试命令。 +/// +public sealed class TestAsyncCommandChildV3 : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommandChildV3(TestCommandInputV2 input) : base(input) + { + } + + /// + /// 获取一个值,该值指示命令是否已经执行。 + /// + public bool Executed { get; private set; } + + /// + /// 获取子类记录的执行值。 + /// + public int ExecutedValue { get; private set; } + + /// + /// 执行子类测试命令并记录经过变换的输入值。 + /// + /// 命令输入。 + /// 已完成的异步任务。 + protected override Task OnExecuteAsync(TestCommandInputV2 input) + { + Executed = true; + ExecutedValue = input.Value * 2; + return Task.CompletedTask; + } +} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommandV3.cs b/GFramework.Core.Tests/Command/TestAsyncCommandV3.cs new file mode 100644 index 00000000..eab5865f --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommandV3.cs @@ -0,0 +1,39 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的无返回值异步测试命令。 +/// +public sealed class TestAsyncCommandV3 : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommandV3(TestCommandInputV2 input) : base(input) + { + } + + /// + /// 获取一个值,该值指示命令是否已经执行。 + /// + public bool Executed { get; private set; } + + /// + /// 获取命令记录的执行值。 + /// + public int ExecutedValue { get; private set; } + + /// + /// 执行测试命令并回写执行状态。 + /// + /// 命令输入。 + /// 已完成的异步任务。 + protected override Task OnExecuteAsync(TestCommandInputV2 input) + { + Executed = true; + ExecutedValue = input.Value; + return Task.CompletedTask; + } +} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommandWithExceptionV3.cs b/GFramework.Core.Tests/Command/TestAsyncCommandWithExceptionV3.cs new file mode 100644 index 00000000..4dc9e2a7 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommandWithExceptionV3.cs @@ -0,0 +1,28 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的异常路径异步测试命令。 +/// +public sealed class TestAsyncCommandWithExceptionV3 : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommandWithExceptionV3(TestCommandInputV2 input) : base(input) + { + } + + /// + /// 执行测试命令并始终抛出预期异常。 + /// + /// 命令输入。 + /// 此方法不会正常返回。 + /// 始终抛出,用于验证异常传播行为。 + protected override Task OnExecuteAsync(TestCommandInputV2 input) + { + throw new InvalidOperationException("Test exception"); + } +} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommandWithResult.cs b/GFramework.Core.Tests/Command/TestAsyncCommandWithResult.cs new file mode 100644 index 00000000..b3fac25f --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommandWithResult.cs @@ -0,0 +1,33 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的带返回值异步测试命令。 +/// +public sealed class TestAsyncCommandWithResult : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommandWithResult(TestCommandInput input) : base(input) + { + } + + /// + /// 获取一个值,该值指示命令是否已经执行。 + /// + public bool Executed { get; private set; } + + /// + /// 执行异步测试命令并返回基于输入值计算的结果。 + /// + /// 命令输入。 + /// 输入值两倍的异步结果。 + protected override Task OnExecuteAsync(TestCommandInput input) + { + Executed = true; + return Task.FromResult(input.Value * 2); + } +} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommandWithResultChildV3.cs b/GFramework.Core.Tests/Command/TestAsyncCommandWithResultChildV3.cs new file mode 100644 index 00000000..20661821 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommandWithResultChildV3.cs @@ -0,0 +1,33 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的子类化带返回值异步测试命令。 +/// +public sealed class TestAsyncCommandWithResultChildV3 : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommandWithResultChildV3(TestCommandInputV2 input) : base(input) + { + } + + /// + /// 获取一个值,该值指示命令是否已经执行。 + /// + public bool Executed { get; private set; } + + /// + /// 执行子类测试命令并返回经过变换的输入值。 + /// + /// 命令输入。 + /// 输入值三倍的异步结果。 + protected override Task OnExecuteAsync(TestCommandInputV2 input) + { + Executed = true; + return Task.FromResult(input.Value * 3); + } +} diff --git a/GFramework.Core.Tests/Command/TestAsyncCommandWithResultV3.cs b/GFramework.Core.Tests/Command/TestAsyncCommandWithResultV3.cs new file mode 100644 index 00000000..43e577b7 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestAsyncCommandWithResultV3.cs @@ -0,0 +1,33 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的带返回值异步测试命令。 +/// +public sealed class TestAsyncCommandWithResultV3 : AbstractAsyncCommand +{ + /// + /// 初始化 的新实例。 + /// + /// 命令输入。 + public TestAsyncCommandWithResultV3(TestCommandInputV2 input) : base(input) + { + } + + /// + /// 获取一个值,该值指示命令是否已经执行。 + /// + public bool Executed { get; private set; } + + /// + /// 执行测试命令并返回基于输入值计算的结果。 + /// + /// 命令输入。 + /// 输入值两倍的异步结果。 + protected override Task OnExecuteAsync(TestCommandInputV2 input) + { + Executed = true; + return Task.FromResult(input.Value * 2); + } +} diff --git a/GFramework.Core.Tests/Command/TestCommand.cs b/GFramework.Core.Tests/Command/TestCommand.cs new file mode 100644 index 00000000..54e3d6b6 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestCommand.cs @@ -0,0 +1,37 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的同步测试命令。 +/// +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; + ExecutedValue = 42; + } +} diff --git a/GFramework.Core.Tests/Command/TestCommandInput.cs b/GFramework.Core.Tests/Command/TestCommandInput.cs new file mode 100644 index 00000000..2ca47099 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestCommandInput.cs @@ -0,0 +1,14 @@ +using GFramework.Cqrs.Abstractions.Cqrs.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的测试命令输入。 +/// +public sealed class TestCommandInput : ICommandInput +{ + /// + /// 获取或设置测试值。 + /// + public int Value { get; init; } +} diff --git a/GFramework.Core.Tests/Command/TestCommandInputV2.cs b/GFramework.Core.Tests/Command/TestCommandInputV2.cs new file mode 100644 index 00000000..943f5d99 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestCommandInputV2.cs @@ -0,0 +1,14 @@ +using GFramework.Cqrs.Abstractions.Cqrs.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的测试命令输入。 +/// +public sealed class TestCommandInputV2 : ICommandInput +{ + /// + /// 获取或设置用于驱动测试断言的输入值。 + /// + public int Value { get; init; } +} diff --git a/GFramework.Core.Tests/Command/TestCommandWithResult.cs b/GFramework.Core.Tests/Command/TestCommandWithResult.cs new file mode 100644 index 00000000..d1de53f5 --- /dev/null +++ b/GFramework.Core.Tests/Command/TestCommandWithResult.cs @@ -0,0 +1,33 @@ +using GFramework.Core.Command; + +namespace GFramework.Core.Tests.Command; + +/// +/// 表示 使用的带返回值同步测试命令。 +/// +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; + return input.Value * 2; + } +} diff --git a/GFramework.Core.Tests/Coroutine/ComplexQuery.cs b/GFramework.Core.Tests/Coroutine/ComplexQuery.cs new file mode 100644 index 00000000..69418cd8 --- /dev/null +++ b/GFramework.Core.Tests/Coroutine/ComplexQuery.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Query; + +namespace GFramework.Core.Tests.Coroutine; + +/// +/// 为 提供复杂对象结果的查询测试替身。 +/// +internal class ComplexQuery : IQuery +{ + private IArchitectureContext? _context; + + /// + /// 获取或设置测试查询使用的名称。 + /// + public string Name { get; set; } = string.Empty; + + /// + /// 获取或设置需要聚合的整数集合。 + /// + public List Values { get; set; } = new(); + + /// + /// 获取或设置附加元数据。 + /// + public Dictionary Metadata { get; set; } = new(StringComparer.Ordinal); + + /// + /// 绑定当前查询所属的架构上下文。 + /// + /// 测试期间由查询管线注入的上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前查询持有的架构上下文。 + /// + /// 此前通过 绑定的上下文实例。 + public IArchitectureContext GetContext() + { + return _context ?? throw new InvalidOperationException( + $"{nameof(SetContext)} must be called before {nameof(GetContext)}."); + } + + /// + /// 执行查询并生成复杂结果对象。 + /// + /// 包含名称、求和值和计数信息的测试结果。 + public ComplexResult Do() + { + return new ComplexResult + { + ProcessedName = Name, + Sum = Values.Sum(), + Count = Values.Count + }; + } +} diff --git a/GFramework.Core.Tests/Coroutine/ComplexResult.cs b/GFramework.Core.Tests/Coroutine/ComplexResult.cs new file mode 100644 index 00000000..c6501114 --- /dev/null +++ b/GFramework.Core.Tests/Coroutine/ComplexResult.cs @@ -0,0 +1,22 @@ +namespace GFramework.Core.Tests.Coroutine; + +/// +/// 为 提供复杂对象结果的测试载体。 +/// +internal class ComplexResult +{ + /// + /// 获取或设置处理后的名称。 + /// + public string ProcessedName { get; set; } = string.Empty; + + /// + /// 获取或设置整数集合的求和结果。 + /// + public int Sum { get; set; } + + /// + /// 获取或设置整数集合中的元素数量。 + /// + public int Count { get; set; } +} diff --git a/GFramework.Core.Tests/Coroutine/CoroutineSchedulerTests.cs b/GFramework.Core.Tests/Coroutine/CoroutineSchedulerTests.cs index 08b0fb8a..991180e3 100644 --- a/GFramework.Core.Tests/Coroutine/CoroutineSchedulerTests.cs +++ b/GFramework.Core.Tests/Coroutine/CoroutineSchedulerTests.cs @@ -610,28 +610,3 @@ public class CoroutineSchedulerTests throw new InvalidOperationException("Test exception"); } } - -/// -/// 测试用时间源类,实现ITimeSource接口 -/// -public class TestTimeSource : ITimeSource -{ - /// - /// 获取当前时间 - /// - public double CurrentTime { get; private set; } - - /// - /// 获取时间增量 - /// - public double DeltaTime { get; private set; } - - /// - /// 更新时间源状态 - /// - public void Update() - { - DeltaTime = 0.1; - CurrentTime += DeltaTime; - } -} diff --git a/GFramework.Core.Tests/Coroutine/IntQuery.cs b/GFramework.Core.Tests/Coroutine/IntQuery.cs new file mode 100644 index 00000000..02b8826e --- /dev/null +++ b/GFramework.Core.Tests/Coroutine/IntQuery.cs @@ -0,0 +1,44 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Query; + +namespace GFramework.Core.Tests.Coroutine; + +/// +/// 为 提供布尔结果的整数查询测试替身。 +/// +internal class IntQuery : IQuery +{ + private IArchitectureContext? _context; + + /// + /// 获取或设置参与查询计算的整数值。 + /// + public int Value { get; set; } + + /// + /// 绑定当前查询所属的架构上下文。 + /// + /// 测试期间由查询管线注入的上下文。 + public void SetContext(IArchitectureContext context) + { + _context = context; + } + + /// + /// 获取当前查询持有的架构上下文。 + /// + /// 此前通过 绑定的上下文实例。 + public IArchitectureContext GetContext() + { + return _context!; + } + + /// + /// 执行查询并返回布尔结果。 + /// + /// 大于零时返回 + public bool Do() + { + return Value > 0; + } +} diff --git a/GFramework.Core.Tests/Coroutine/QueryCoroutineExtensionsTests.cs b/GFramework.Core.Tests/Coroutine/QueryCoroutineExtensionsTests.cs index 78b97394..e608b660 100644 --- a/GFramework.Core.Tests/Coroutine/QueryCoroutineExtensionsTests.cs +++ b/GFramework.Core.Tests/Coroutine/QueryCoroutineExtensionsTests.cs @@ -329,63 +329,3 @@ public class QueryCoroutineExtensionsTests Assert.That(receivedResult, Is.Null); } } - -/// -/// 用于测试的整数查询类 -/// -internal class IntQuery : IQuery -{ - private IArchitectureContext? _context; - public int Value { get; set; } - - public void SetContext(IArchitectureContext context) - { - _context = context; - } - - public IArchitectureContext GetContext() - { - return _context!; - } - - public bool Do() - { - return Value > 0; - } -} - -/// -/// 用于测试的复杂查询类 -/// -internal class ComplexQuery : IQuery -{ - private IArchitectureContext? _context; - public string Name { get; set; } = string.Empty; - public List Values { get; set; } = new(); - public Dictionary Metadata { get; set; } = new(StringComparer.Ordinal); - - public void SetContext(IArchitectureContext context) - { - _context = context; - } - - public IArchitectureContext GetContext() - { - return _context!; - } - - public ComplexResult Do() - { - return new ComplexResult { ProcessedName = Name, Sum = Values.Sum(), Count = Values.Count }; - } -} - -/// -/// 用于测试的复杂结果类 -/// -internal class ComplexResult -{ - public string ProcessedName { get; set; } = string.Empty; - public int Sum { get; set; } - public int Count { get; set; } -} diff --git a/GFramework.Core.Tests/Coroutine/TestTimeSource.cs b/GFramework.Core.Tests/Coroutine/TestTimeSource.cs new file mode 100644 index 00000000..9a62c954 --- /dev/null +++ b/GFramework.Core.Tests/Coroutine/TestTimeSource.cs @@ -0,0 +1,28 @@ +using GFramework.Core.Abstractions.Coroutine; + +namespace GFramework.Core.Tests.Coroutine; + +/// +/// 为协程测试提供固定时间步长的时间源。 +/// +public sealed class TestTimeSource : ITimeSource +{ + /// + /// 获取当前累计时间。 + /// + public double CurrentTime { get; private set; } + + /// + /// 获取最近一次更新产生的时间增量。 + /// + public double DeltaTime { get; private set; } + + /// + /// 按固定步长推进测试时间,确保调度器测试具有确定性。 + /// + public void Update() + { + DeltaTime = 0.1; + CurrentTime += DeltaTime; + } +} diff --git a/GFramework.Core.Tests/Cqrs/DeterministicOrderNotification.cs b/GFramework.Core.Tests/Cqrs/DeterministicOrderNotification.cs new file mode 100644 index 00000000..ec18eb14 --- /dev/null +++ b/GFramework.Core.Tests/Cqrs/DeterministicOrderNotification.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2026 GeWuYou +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using GFramework.Cqrs.Abstractions.Cqrs; + +namespace GFramework.Core.Tests.Cqrs; + +/// +/// 为容器层测试提供可扫描的最小通知夹具。 +/// +internal sealed record DeterministicOrderNotification : INotification; diff --git a/GFramework.Core.Tests/Cqrs/ContainerRegistrationFixtures.cs b/GFramework.Core.Tests/Cqrs/DeterministicOrderNotificationHandler.cs similarity index 88% rename from GFramework.Core.Tests/Cqrs/ContainerRegistrationFixtures.cs rename to GFramework.Core.Tests/Cqrs/DeterministicOrderNotificationHandler.cs index 9406ede7..59945c83 100644 --- a/GFramework.Core.Tests/Cqrs/ContainerRegistrationFixtures.cs +++ b/GFramework.Core.Tests/Cqrs/DeterministicOrderNotificationHandler.cs @@ -2,24 +2,20 @@ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Threading; using GFramework.Cqrs.Abstractions.Cqrs; namespace GFramework.Core.Tests.Cqrs; -/// -/// 为容器层测试提供可扫描的最小通知夹具。 -/// -internal sealed record DeterministicOrderNotification : INotification; - /// /// 供容器注册测试验证程序集扫描结果的通知处理器。 /// diff --git a/GFramework.Core.Tests/Environment/EnvironmentTests.cs b/GFramework.Core.Tests/Environment/EnvironmentTests.cs index 49056cfb..79f9cfc2 100644 --- a/GFramework.Core.Tests/Environment/EnvironmentTests.cs +++ b/GFramework.Core.Tests/Environment/EnvironmentTests.cs @@ -49,7 +49,7 @@ public class EnvironmentTests [Test] public void Get_Should_Return_Value_When_Key_Exists() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.Get("testKey"); @@ -73,7 +73,7 @@ public class EnvironmentTests [Test] public void Get_Should_ReturnNull_When_Type_Does_Not_Match() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.Get>("testKey"); @@ -86,7 +86,7 @@ public class EnvironmentTests [Test] public void TryGet_Should_ReturnTrue_And_Value_When_Key_Exists() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.TryGet("testKey", out var value); @@ -112,7 +112,7 @@ public class EnvironmentTests [Test] public void TryGet_Should_ReturnFalse_When_Type_Does_Not_Match() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.TryGet>("testKey", out var value); @@ -126,7 +126,7 @@ public class EnvironmentTests [Test] public void GetRequired_Should_Return_Value_When_Key_Exists() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.GetRequired("testKey"); @@ -149,7 +149,7 @@ public class EnvironmentTests [Test] public void Register_Should_Add_Value_To_Dictionary() { - _environment.Register("newKey", "newValue"); + _environment.RegisterForTest("newKey", "newValue"); var result = _environment.Get("newKey"); @@ -162,8 +162,8 @@ public class EnvironmentTests [Test] public void Register_Should_Overwrite_Existing_Value() { - _environment.Register("testKey", "value1"); - _environment.Register("testKey", "value2"); + _environment.RegisterForTest("testKey", "value1"); + _environment.RegisterForTest("testKey", "value2"); var result = _environment.Get("testKey"); @@ -184,31 +184,3 @@ public class EnvironmentTests Assert.That(result, Is.EqualTo("interfaceValue")); } } - -/// -/// 测试环境实现类,继承自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() - { - } -} \ No newline at end of file diff --git a/GFramework.Core.Tests/Environment/TestEnvironment.cs b/GFramework.Core.Tests/Environment/TestEnvironment.cs new file mode 100644 index 00000000..10ce3c0c --- /dev/null +++ b/GFramework.Core.Tests/Environment/TestEnvironment.cs @@ -0,0 +1,34 @@ +using GFramework.Core.Environment; + +namespace GFramework.Core.Tests.Environment; + +/// +/// 为环境相关测试提供可写注册入口的测试环境实现。 +/// +public sealed class TestEnvironment : EnvironmentBase +{ + /// + /// 获取测试环境名称。 + /// + public override string Name { get; } = "TestEnvironment"; + + /// + /// 将测试数据注册到基础环境存储中,便于测试通过显式测试辅助入口准备上下文。 + /// + /// 要注册的环境键。 + /// 要注册的环境值。 + public void RegisterForTest(string key, object value) + { + base.Register(key, value); + } + + /// + /// 初始化测试环境。 + /// + /// + /// 当前测试环境没有额外初始化逻辑,但仍保留重写以匹配 契约。 + /// + public override void Initialize() + { + } +} diff --git a/GFramework.Core.Tests/Events/EventBusTests.cs b/GFramework.Core.Tests/Events/EventBusTests.cs index 385cbccb..1eb027b3 100644 --- a/GFramework.Core.Tests/Events/EventBusTests.cs +++ b/GFramework.Core.Tests/Events/EventBusTests.cs @@ -76,10 +76,3 @@ public class EventBusTests Assert.That(count2, Is.EqualTo(1)); } } - -/// -/// EventBus测试专用事件类 -/// -public class EventBusTestsEvent -{ -} \ No newline at end of file diff --git a/GFramework.Core.Tests/Events/EventBusTestsEvent.cs b/GFramework.Core.Tests/Events/EventBusTestsEvent.cs new file mode 100644 index 00000000..6bca770c --- /dev/null +++ b/GFramework.Core.Tests/Events/EventBusTestsEvent.cs @@ -0,0 +1,8 @@ +namespace GFramework.Core.Tests.Events; + +/// +/// 表示 使用的测试事件。 +/// +public class EventBusTestsEvent +{ +} diff --git a/GFramework.Core.Tests/Extensions/ObjectExtensionsTests.cs b/GFramework.Core.Tests/Extensions/ObjectExtensionsTests.cs index 411069a9..14209d8d 100644 --- a/GFramework.Core.Tests/Extensions/ObjectExtensionsTests.cs +++ b/GFramework.Core.Tests/Extensions/ObjectExtensionsTests.cs @@ -218,19 +218,3 @@ public class ObjectExtensionsTests Assert.That(executed, Is.False); } } - -/// -/// 测试用的简单类 -/// -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/TestClass.cs b/GFramework.Core.Tests/Extensions/TestClass.cs new file mode 100644 index 00000000..e13683d0 --- /dev/null +++ b/GFramework.Core.Tests/Extensions/TestClass.cs @@ -0,0 +1,17 @@ +namespace GFramework.Core.Tests.Extensions; + +/// +/// 为 提供类型匹配断言所需的简单测试对象。 +/// +public class TestClass +{ + /// + /// 获取或设置用于数值分支断言的测试值。 + /// + public int Value { get; set; } + + /// + /// 获取或设置用于字符串结果断言的测试名称。 + /// + public string Name { get; set; } = string.Empty; +} diff --git a/GFramework.Core.Tests/Extensions/TestUnRegisterList.cs b/GFramework.Core.Tests/Extensions/TestUnRegisterList.cs new file mode 100644 index 00000000..25ed33a6 --- /dev/null +++ b/GFramework.Core.Tests/Extensions/TestUnRegisterList.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using GFramework.Core.Abstractions.Events; + +namespace GFramework.Core.Tests.Extensions; + +/// +/// 为 提供可观察的 测试替身。 +/// +public class TestUnRegisterList : IUnRegisterList +{ + /// + /// 获取当前测试收集到的注销项列表,供断言扩展方法是否正确追加和清空元素。 + /// + public IList UnregisterList { get; } = new List(); +} diff --git a/GFramework.Core.Tests/Extensions/UnRegisterListExtensionTests.cs b/GFramework.Core.Tests/Extensions/UnRegisterListExtensionTests.cs index 8865fdc2..fb2d4864 100644 --- a/GFramework.Core.Tests/Extensions/UnRegisterListExtensionTests.cs +++ b/GFramework.Core.Tests/Extensions/UnRegisterListExtensionTests.cs @@ -1,4 +1,3 @@ -using GFramework.Core.Abstractions.Events; using GFramework.Core.Events; using GFramework.Core.Extensions; using NUnit.Framework; @@ -119,14 +118,3 @@ public class UnRegisterListExtensionTests 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/Pool/ObjectPoolTests.cs b/GFramework.Core.Tests/Pool/ObjectPoolTests.cs index bb7bd360..44ebc909 100644 --- a/GFramework.Core.Tests/Pool/ObjectPoolTests.cs +++ b/GFramework.Core.Tests/Pool/ObjectPoolTests.cs @@ -1,5 +1,3 @@ -using GFramework.Core.Abstractions.Pool; -using GFramework.Core.Pool; using NUnit.Framework; namespace GFramework.Core.Tests.Pool; @@ -285,81 +283,3 @@ public class ObjectPoolTests Assert.That(_pool.GetActiveCount("key2"), Is.EqualTo(0)); } } - -/// -/// 测试用对象池实现类,继承自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; - } -} \ No newline at end of file diff --git a/GFramework.Core.Tests/Pool/TestObjectPool.cs b/GFramework.Core.Tests/Pool/TestObjectPool.cs new file mode 100644 index 00000000..303db8db --- /dev/null +++ b/GFramework.Core.Tests/Pool/TestObjectPool.cs @@ -0,0 +1,27 @@ +using GFramework.Core.Pool; + +namespace GFramework.Core.Tests.Pool; + +/// +/// 测试用对象池实现类,继承自 , +/// 用于验证对象池的获取、释放和统计行为。 +/// +public class TestObjectPool : AbstractObjectPoolSystem +{ + /// + /// 根据池键创建新的测试对象。 + /// + /// 用于标识对象所属池的键。 + /// 带有对应 的测试对象实例。 + protected override TestPoolableObject Create(string key) + { + return new TestPoolableObject { PoolKey = key }; + } + + /// + /// 执行对象池初始化。 + /// + protected override void OnInit() + { + } +} diff --git a/GFramework.Core.Tests/Pool/TestPoolableObject.cs b/GFramework.Core.Tests/Pool/TestPoolableObject.cs new file mode 100644 index 00000000..2b1f0750 --- /dev/null +++ b/GFramework.Core.Tests/Pool/TestPoolableObject.cs @@ -0,0 +1,58 @@ +using GFramework.Core.Abstractions.Pool; + +namespace GFramework.Core.Tests.Pool; + +/// +/// 供对象池测试使用的池化对象,记录生命周期回调是否被触发。 +/// +public class TestPoolableObject : IPoolableObject +{ + /// + /// 获取或设置对象所属的池键。 + /// + public string PoolKey { get; set; } = string.Empty; + + /// + /// 获取或设置测试中写入的整数值。 + /// + public int TestValue { get; set; } + + /// + /// 获取或设置对象获取回调是否已执行。 + /// + public bool OnAcquireCalled { get; set; } + + /// + /// 获取或设置对象释放回调是否已执行。 + /// + public bool OnReleaseCalled { get; set; } + + /// + /// 获取或设置对象销毁回调是否已执行。 + /// + 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/Query/AbstractAsyncQueryTests.cs b/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs index 305c5f0d..6a0edde2 100644 --- a/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs +++ b/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs @@ -212,7 +212,7 @@ public class AbstractAsyncQueryTests Assert.That(result, Is.Not.Null); Assert.That(result.Value, Is.EqualTo(20)); - Assert.That(result.DoubleValue, Is.EqualTo(30)); + Assert.That(result.TripleValue, Is.EqualTo(30)); } /// diff --git a/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs b/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs index acf0cc84..06844ab0 100644 --- a/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs +++ b/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs @@ -1,5 +1,4 @@ using GFramework.Core.Query; -using GFramework.Cqrs.Abstractions.Cqrs.Query; namespace GFramework.Core.Tests.Query; @@ -88,7 +87,7 @@ public class AsyncQueryExecutorTests Assert.That(result, Is.Not.Null); Assert.That(result.Value, Is.EqualTo(200)); - Assert.That(result.DoubleValue, Is.EqualTo(300)); + Assert.That(result.TripleValue, Is.EqualTo(300)); } /// @@ -137,159 +136,3 @@ public class AsyncQueryExecutorTests Assert.That(result2, Is.EqualTo(40)); } } - -/// -/// 测试用异步查询输入类,实现IQueryInput接口 -/// -public sealed class TestAsyncQueryInput : IQueryInput -{ - /// - /// 获取或设置查询值 - /// - public int Value { get; init; } -} - -/// -/// 整数类型测试异步查询类,继承AbstractAsyncQuery -/// 实现具体的异步查询逻辑并返回整数结果 -/// -public sealed class TestAsyncQuery : AbstractAsyncQuery -{ - /// - /// 初始化TestAsyncQuery的新实例 - /// - /// 查询输入参数 - public TestAsyncQuery(TestAsyncQueryInput input) : base(input) - { - } - - /// - /// 执行异步查询操作的具体实现 - /// - /// 查询输入参数 - /// 查询结果,将输入值乘以2 - protected override Task OnDoAsync(TestAsyncQueryInput input) - { - return Task.FromResult(input.Value * 2); - } -} - -/// -/// 字符串类型测试异步查询类,继承AbstractAsyncQuery -/// 实现具体的异步查询逻辑并返回字符串结果 -/// -public sealed class TestAsyncStringQuery : AbstractAsyncQuery -{ - /// - /// 初始化TestAsyncStringQuery的新实例 - /// - /// 查询输入参数 - public TestAsyncStringQuery(TestAsyncQueryInput input) : base(input) - { - } - - /// - /// 执行异步查询操作的具体实现 - /// - /// 查询输入参数 - /// 格式化的字符串结果 - protected override Task OnDoAsync(TestAsyncQueryInput input) - { - return Task.FromResult($"Result: {input.Value * 2}"); - } -} - -/// -/// 布尔类型测试异步查询类,继承AbstractAsyncQuery -/// 实现具体的异步查询逻辑并返回布尔结果 -/// -public sealed class TestAsyncBooleanQuery : AbstractAsyncQuery -{ - /// - /// 初始化TestAsyncBooleanQuery的新实例 - /// - /// 查询输入参数 - public TestAsyncBooleanQuery(TestAsyncQueryInput input) : base(input) - { - } - - /// - /// 执行异步查询操作的具体实现 - /// - /// 查询输入参数 - /// 如果值大于0返回true,否则返回false - protected override Task OnDoAsync(TestAsyncQueryInput input) - { - return Task.FromResult(input.Value > 0); - } -} - -/// -/// 复杂对象类型测试异步查询类,继承AbstractAsyncQuery -/// 实现具体的异步查询逻辑并返回复杂对象结果 -/// -public sealed class TestAsyncComplexQuery : AbstractAsyncQuery -{ - /// - /// 初始化TestAsyncComplexQuery的新实例 - /// - /// 查询输入参数 - public TestAsyncComplexQuery(TestAsyncQueryInput input) : base(input) - { - } - - /// - /// 执行异步查询操作的具体实现 - /// - /// 查询输入参数 - /// 复杂对象查询结果 - protected override Task OnDoAsync(TestAsyncQueryInput input) - { - var result = new TestAsyncQueryResult - { - Value = input.Value * 2, - DoubleValue = input.Value * 3 - }; - return Task.FromResult(result); - } -} - -/// -/// 测试用异步查询类(抛出异常) -/// -public sealed class TestAsyncQueryWithException : AbstractAsyncQuery -{ - /// - /// 初始化TestAsyncQueryWithException的新实例 - /// - /// 查询输入参数 - public TestAsyncQueryWithException(TestAsyncQueryInput input) : base(input) - { - } - - /// - /// 执行异步查询操作并抛出异常 - /// - /// 查询输入参数 - /// 总是抛出异常 - protected override Task OnDoAsync(TestAsyncQueryInput input) - { - throw new InvalidOperationException("Test exception"); - } -} - -/// -/// 测试用复杂查询结果类 -/// -public sealed class TestAsyncQueryResult -{ - /// - /// 获取或设置值 - /// - public int Value { get; init; } - - /// - /// 获取或设置双倍值 - /// - public int DoubleValue { get; init; } -} diff --git a/GFramework.Core.Tests/Query/QueryExecutorTests.cs b/GFramework.Core.Tests/Query/QueryExecutorTests.cs index a9cde117..b6feeac3 100644 --- a/GFramework.Core.Tests/Query/QueryExecutorTests.cs +++ b/GFramework.Core.Tests/Query/QueryExecutorTests.cs @@ -1,5 +1,4 @@ using GFramework.Core.Query; -using GFramework.Cqrs.Abstractions.Cqrs.Query; namespace GFramework.Core.Tests.Query; @@ -60,65 +59,3 @@ public class QueryExecutorTests Assert.That(result, Is.EqualTo("Result: 10")); } } - -/// -/// 测试用查询输入类,实现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/Query/TestAsyncBooleanQuery.cs b/GFramework.Core.Tests/Query/TestAsyncBooleanQuery.cs new file mode 100644 index 00000000..ccf2f635 --- /dev/null +++ b/GFramework.Core.Tests/Query/TestAsyncBooleanQuery.cs @@ -0,0 +1,27 @@ +using GFramework.Core.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供布尔结果的测试异步查询。 +/// +public sealed class TestAsyncBooleanQuery : AbstractAsyncQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + public TestAsyncBooleanQuery(TestAsyncQueryInput input) : base(input) + { + } + + /// + /// 执行异步查询并根据输入值是否大于零返回布尔结果。 + /// + /// 查询输入参数。 + /// 当输入值大于 0 时返回 ;否则返回 + protected override Task OnDoAsync(TestAsyncQueryInput input) + { + return Task.FromResult(input.Value > 0); + } +} diff --git a/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs b/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs new file mode 100644 index 00000000..ca575a3c --- /dev/null +++ b/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs @@ -0,0 +1,33 @@ +using GFramework.Core.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供复杂对象结果的测试异步查询。 +/// +public sealed class TestAsyncComplexQuery : AbstractAsyncQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + public TestAsyncComplexQuery(TestAsyncQueryInput input) : base(input) + { + } + + /// + /// 执行异步查询并构造组合结果对象。 + /// + /// 查询输入参数。 + /// 包含双倍值和三倍值的测试结果对象。 + protected override Task OnDoAsync(TestAsyncQueryInput input) + { + var result = new TestAsyncQueryResult + { + Value = input.Value * 2, + TripleValue = input.Value * 3 + }; + + return Task.FromResult(result); + } +} diff --git a/GFramework.Core.Tests/Query/TestAsyncComplexQueryV4.cs b/GFramework.Core.Tests/Query/TestAsyncComplexQueryV4.cs index a5661efb..01e854e7 100644 --- a/GFramework.Core.Tests/Query/TestAsyncComplexQueryV4.cs +++ b/GFramework.Core.Tests/Query/TestAsyncComplexQueryV4.cs @@ -31,7 +31,7 @@ public sealed class TestAsyncComplexQueryV4 : AbstractAsyncQuery +/// 为 提供整数结果的测试异步查询。 +/// +public sealed class TestAsyncQuery : AbstractAsyncQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + public TestAsyncQuery(TestAsyncQueryInput input) : base(input) + { + } + + /// + /// 执行异步查询并返回输入值的两倍。 + /// + /// 查询输入参数。 + /// 将输入值乘以 2 的结果。 + protected override Task OnDoAsync(TestAsyncQueryInput input) + { + return Task.FromResult(input.Value * 2); + } +} diff --git a/GFramework.Core.Tests/Query/TestAsyncQueryInput.cs b/GFramework.Core.Tests/Query/TestAsyncQueryInput.cs new file mode 100644 index 00000000..67b59855 --- /dev/null +++ b/GFramework.Core.Tests/Query/TestAsyncQueryInput.cs @@ -0,0 +1,14 @@ +using GFramework.Cqrs.Abstractions.Cqrs.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供输入值的测试查询输入。 +/// +public sealed class TestAsyncQueryInput : IQueryInput +{ + /// + /// 获取查询值;该值只能在对象初始化阶段设置。 + /// + public int Value { get; init; } +} diff --git a/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs b/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs new file mode 100644 index 00000000..ea156ef4 --- /dev/null +++ b/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs @@ -0,0 +1,17 @@ +namespace GFramework.Core.Tests.Query; + +/// +/// 表示 使用的复杂测试查询结果。 +/// +public sealed class TestAsyncQueryResult +{ + /// + /// 获取主结果值;该值只能在对象初始化阶段设置。 + /// + public int Value { get; init; } + + /// + /// 获取派生的三倍结果值;该值只能在对象初始化阶段设置。 + /// + public int TripleValue { get; init; } +} diff --git a/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs b/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs index 068b2a66..91174cef 100644 --- a/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs +++ b/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs @@ -6,12 +6,12 @@ namespace GFramework.Core.Tests.Query; public sealed class TestAsyncQueryResultV2 { /// - /// 获取或设置值 + /// 获取值;该值只能在对象初始化阶段设置。 /// public int Value { get; init; } /// - /// 获取或设置双倍值 + /// 获取三倍值;该值只能在对象初始化阶段设置。 /// - public int DoubleValue { get; init; } + public int TripleValue { get; init; } } diff --git a/GFramework.Core.Tests/Query/TestAsyncQueryWithException.cs b/GFramework.Core.Tests/Query/TestAsyncQueryWithException.cs new file mode 100644 index 00000000..a5a11da5 --- /dev/null +++ b/GFramework.Core.Tests/Query/TestAsyncQueryWithException.cs @@ -0,0 +1,28 @@ +using GFramework.Core.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供固定抛出异常的测试异步查询。 +/// +public sealed class TestAsyncQueryWithException : AbstractAsyncQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + public TestAsyncQueryWithException(TestAsyncQueryInput input) : base(input) + { + } + + /// + /// 执行异步查询并始终抛出测试异常。 + /// + /// 查询输入参数。 + /// 此方法不会返回结果。 + /// 始终抛出,模拟查询执行失败。 + protected override Task OnDoAsync(TestAsyncQueryInput input) + { + throw new InvalidOperationException("Test exception"); + } +} diff --git a/GFramework.Core.Tests/Query/TestAsyncStringQuery.cs b/GFramework.Core.Tests/Query/TestAsyncStringQuery.cs new file mode 100644 index 00000000..6224f0f7 --- /dev/null +++ b/GFramework.Core.Tests/Query/TestAsyncStringQuery.cs @@ -0,0 +1,27 @@ +using GFramework.Core.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供字符串结果的测试异步查询。 +/// +public sealed class TestAsyncStringQuery : AbstractAsyncQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + public TestAsyncStringQuery(TestAsyncQueryInput input) : base(input) + { + } + + /// + /// 执行异步查询并返回格式化的字符串结果。 + /// + /// 查询输入参数。 + /// 包含双倍值的格式化字符串。 + protected override Task OnDoAsync(TestAsyncQueryInput input) + { + return Task.FromResult($"Result: {input.Value * 2}"); + } +} diff --git a/GFramework.Core.Tests/Query/TestQuery.cs b/GFramework.Core.Tests/Query/TestQuery.cs new file mode 100644 index 00000000..d6a1acd2 --- /dev/null +++ b/GFramework.Core.Tests/Query/TestQuery.cs @@ -0,0 +1,27 @@ +using GFramework.Core.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供整数结果的测试同步查询。 +/// +public sealed class TestQuery : AbstractQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + public TestQuery(TestQueryInput input) : base(input) + { + } + + /// + /// 执行同步查询并返回输入值的双倍结果。 + /// + /// 查询输入参数。 + /// 输入值乘以 2 后的结果。 + protected override int OnDo(TestQueryInput input) + { + return input.Value * 2; + } +} diff --git a/GFramework.Core.Tests/Query/TestQueryInput.cs b/GFramework.Core.Tests/Query/TestQueryInput.cs new file mode 100644 index 00000000..e683e3aa --- /dev/null +++ b/GFramework.Core.Tests/Query/TestQueryInput.cs @@ -0,0 +1,14 @@ +using GFramework.Cqrs.Abstractions.Cqrs.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供输入值的测试查询输入。 +/// +public sealed class TestQueryInput : IQueryInput +{ + /// + /// 获取或设置查询值。 + /// + public int Value { get; init; } +} diff --git a/GFramework.Core.Tests/Query/TestStringQuery.cs b/GFramework.Core.Tests/Query/TestStringQuery.cs new file mode 100644 index 00000000..04c0df5a --- /dev/null +++ b/GFramework.Core.Tests/Query/TestStringQuery.cs @@ -0,0 +1,27 @@ +using GFramework.Core.Query; + +namespace GFramework.Core.Tests.Query; + +/// +/// 为 提供字符串结果的测试同步查询。 +/// +public sealed class TestStringQuery : AbstractQuery +{ + /// + /// 初始化 的新实例。 + /// + /// 查询输入参数。 + 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 7c659310..d446c3bc 100644 --- a/GFramework.Core.Tests/Rule/ContextAwareTests.cs +++ b/GFramework.Core.Tests/Rule/ContextAwareTests.cs @@ -99,29 +99,3 @@ public class ContextAwareTests Assert.DoesNotThrow(() => aware.GetContext()); } } - -/// -/// 用于测试的 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; - } -} \ No newline at end of file diff --git a/GFramework.Core.Tests/Rule/TestContextAware.cs b/GFramework.Core.Tests/Rule/TestContextAware.cs new file mode 100644 index 00000000..df2ba7cf --- /dev/null +++ b/GFramework.Core.Tests/Rule/TestContextAware.cs @@ -0,0 +1,28 @@ +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Rule; + +namespace GFramework.Core.Tests.Rule; + +/// +/// 提供给 ContextAware 相关测试复用的上下文感知对象。 +/// +public class TestContextAware : ContextAwareBase +{ + /// + /// 获取当前测试对象已绑定的上下文实例。 + /// + public IArchitectureContext? PublicContext => Context; + + /// + /// 获取一个值,指示上下文就绪回调是否已经触发。 + /// + public bool OnContextReadyCalled { get; private set; } + + /// + /// 在上下文完成绑定后记录回调已被触发,供断言使用。 + /// + protected override void OnContextReady() + { + OnContextReadyCalled = true; + } +} diff --git a/GFramework.Core.Tests/State/ConcreteAsyncStateV2.cs b/GFramework.Core.Tests/State/ConcreteAsyncStateV2.cs new file mode 100644 index 00000000..7809026d --- /dev/null +++ b/GFramework.Core.Tests/State/ConcreteAsyncStateV2.cs @@ -0,0 +1,116 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 异步具体状态实现类V2版本,用于测试异步状态的基本功能。 +/// +public sealed class ConcreteAsyncStateV2 : IState, IAsyncState +{ + /// + /// 获取或设置是否允许转换。 + /// + public bool AllowTransitions { get; set; } = true; + + /// + /// 获取进入状态是否被调用的标志。 + /// + public bool EnterCalled { get; private set; } + + /// + /// 获取退出状态是否被调用的标志。 + /// + public bool ExitCalled { get; private set; } + + /// + /// 获取进入状态被调用的次数。 + /// + public int EnterCallCount { get; private set; } + + /// + /// 获取退出状态被调用的次数。 + /// + public int ExitCallCount { get; private set; } + + /// + /// 获取进入此状态的来源状态。 + /// + public IState? EnterFrom { get; private set; } + + /// + /// 获取从此状态退出的目标状态。 + /// + public IState? ExitTo { get; private set; } + + /// + /// 获取或设置转换到目标状态时执行的动作。 + /// + public Action? CanTransitionToAsyncAction { get; set; } + + /// + /// 异步进入当前状态时调用的方法。 + /// + /// 从哪个状态进入。 + public async Task OnEnterAsync(IState? from) + { + await Task.Delay(1).ConfigureAwait(false); + EnterCalled = true; + EnterCallCount++; + EnterFrom = from; + } + + /// + /// 异步退出当前状态时调用的方法。 + /// + /// 退出到哪个状态。 + public async Task OnExitAsync(IState? to) + { + await Task.Delay(1).ConfigureAwait(false); + ExitCalled = true; + ExitCallCount++; + ExitTo = to; + } + + /// + /// 异步判断是否可以转换到目标状态。 + /// + /// 目标状态。 + /// 如果可以转换则返回 ,否则返回 + public async Task CanTransitionToAsync(IState target) + { + await Task.Delay(1).ConfigureAwait(false); + CanTransitionToAsyncAction?.Invoke(target); + return AllowTransitions; + } + + /// + /// 进入当前状态时调用的方法(同步版本,抛出异常表示不应被调用)。 + /// + /// 从哪个状态进入。 + /// 总是抛出,表示异步状态不应走同步入口。 + public void OnEnter(IState? from) + { + throw new InvalidOperationException("Sync OnEnter should not be called for async state"); + } + + /// + /// 退出当前状态时调用的方法(同步版本,抛出异常表示不应被调用)。 + /// + /// 退出到哪个状态。 + /// 总是抛出,表示异步状态不应走同步入口。 + public void OnExit(IState? to) + { + throw new InvalidOperationException("Sync OnExit should not be called for async state"); + } + + /// + /// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用)。 + /// + /// 目标状态。 + /// 此方法不会正常返回。 + /// 总是抛出,表示异步状态不应走同步入口。 + public bool CanTransitionTo(IState target) + { + throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state"); + } +} diff --git a/GFramework.Core.Tests/State/ConcreteStateV2.cs b/GFramework.Core.Tests/State/ConcreteStateV2.cs new file mode 100644 index 00000000..b424aa8a --- /dev/null +++ b/GFramework.Core.Tests/State/ConcreteStateV2.cs @@ -0,0 +1,70 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 具体状态实现类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; + } + + /// + /// 判断是否可以转换到目标状态。 + /// + /// 目标状态。 + /// 如果可以转换则返回 ,否则返回 + public bool CanTransitionTo(IState target) + { + CanTransitionToAction?.Invoke(target); + return AllowTransitions; + } +} diff --git a/GFramework.Core.Tests/State/ConcreteStateV3.cs b/GFramework.Core.Tests/State/ConcreteStateV3.cs new file mode 100644 index 00000000..245d72f0 --- /dev/null +++ b/GFramework.Core.Tests/State/ConcreteStateV3.cs @@ -0,0 +1,59 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 具体状态实现类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; + } + + /// + /// 判断是否可以转换到目标状态。 + /// + /// 目标状态。 + /// 始终返回 + public bool CanTransitionTo(IState target) + { + return true; + } +} diff --git a/GFramework.Core.Tests/State/ConcreteStateV4.cs b/GFramework.Core.Tests/State/ConcreteStateV4.cs new file mode 100644 index 00000000..3a919e11 --- /dev/null +++ b/GFramework.Core.Tests/State/ConcreteStateV4.cs @@ -0,0 +1,59 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 具体状态实现类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; + } + + /// + /// 判断是否可以转换到目标状态。 + /// + /// 目标状态。 + /// 始终返回 + public bool CanTransitionTo(IState target) + { + return true; + } +} diff --git a/GFramework.Core.Tests/State/ConditionalStateV2.cs b/GFramework.Core.Tests/State/ConditionalStateV2.cs new file mode 100644 index 00000000..53715f4d --- /dev/null +++ b/GFramework.Core.Tests/State/ConditionalStateV2.cs @@ -0,0 +1,64 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 条件状态实现类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; + } + + /// + /// 判断是否可以转换到目标状态。 + /// + /// 目标状态。 + /// 如果目标状态类型在允许列表中则返回 ,否则返回 + public bool CanTransitionTo(IState target) + { + return AllowedTransitions.Contains(target.GetType()); + } +} diff --git a/GFramework.Core.Tests/State/StateMachineExtensions.cs b/GFramework.Core.Tests/State/StateMachineExtensions.cs new file mode 100644 index 00000000..685471a9 --- /dev/null +++ b/GFramework.Core.Tests/State/StateMachineExtensions.cs @@ -0,0 +1,24 @@ +using System.Reflection; +using GFramework.Core.Abstractions.State; +using GFramework.Core.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为状态机测试提供仅限断言场景使用的反射辅助方法。 +/// +public static class StateMachineExtensions +{ + /// + /// 检查状态机内部缓存中是否已注册指定类型的状态。 + /// + /// 要检查的状态类型。 + /// 待检查的状态机实例。 + /// 找到对应状态类型时返回 ,否则返回 + public static bool ContainsState(this StateMachine stateMachine) where T : IState + { + return stateMachine.GetType().GetField("States", BindingFlags.NonPublic | BindingFlags.Instance)? + .GetValue(stateMachine) is Dictionary states && + states.ContainsKey(typeof(T)); + } +} diff --git a/GFramework.Core.Tests/State/StateMachineSystemTests.cs b/GFramework.Core.Tests/State/StateMachineSystemTests.cs index 63cb5b22..cb22d56d 100644 --- a/GFramework.Core.Tests/State/StateMachineSystemTests.cs +++ b/GFramework.Core.Tests/State/StateMachineSystemTests.cs @@ -1,7 +1,6 @@ using System.Reflection; using GFramework.Core.Abstractions.Enums; using GFramework.Core.Abstractions.Logging; -using GFramework.Core.Abstractions.State; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Architectures; using GFramework.Core.Command; @@ -238,140 +237,3 @@ public class StateMachineSystemTests Assert.That(eventCount, Is.EqualTo(3)); } } - -#region Test Classes - -/// -/// 测试用的ContextAwareStateMachine派生类,用于访问内部状态字典 -/// -public class TestStateMachineSystemV5 : StateMachineSystem -{ - /// - /// 获取状态机内部的状态字典 - /// - /// 类型到状态实例的映射字典 - public IDictionary GetStates() - { - return 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) - { - return true; - } - - /// - /// 进入状态时调用 - /// - /// 前一个状态 - public void OnEnter(IState? previous) - { - } - - /// - /// 退出状态时调用 - /// - /// 下一个状态 - public void OnExit(IState? next) - { - } -} - -/// -/// 第二个测试用的普通状态实现,用于区分不同状态类型 -/// -public class TestStateV5_2 : IState -{ - /// - /// 状态标识符 - /// - public int Id { get; set; } - - /// - /// 检查是否可以转换到指定状态 - /// - /// 目标状态 - /// 始终返回true表示允许转换 - public bool CanTransitionTo(IState next) - { - return true; - } - - /// - /// 进入状态时调用 - /// - /// 前一个状态 - public void OnEnter(IState? previous) - { - } - - /// - /// 退出状态时调用 - /// - /// 下一个状态 - public void OnExit(IState? next) - { - } -} - -#endregion diff --git a/GFramework.Core.Tests/State/StateMachineTests.cs b/GFramework.Core.Tests/State/StateMachineTests.cs index 9edfb036..f8fbf2c6 100644 --- a/GFramework.Core.Tests/State/StateMachineTests.cs +++ b/GFramework.Core.Tests/State/StateMachineTests.cs @@ -1,4 +1,3 @@ -using System.Reflection; using GFramework.Core.Abstractions.State; using GFramework.Core.State; using NUnit.Framework; @@ -246,7 +245,7 @@ public class StateMachineTests [Test] public async Task ChangeToAsync_WhenCurrentStateDeniesTransition_WithAsyncState_Should_Call_CanTransitionToAsync() { - var state1 = new TestAsyncState { AllowTransition = false }; + var state1 = new TestAsyncState { AllowTransitions = false }; var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); @@ -368,237 +367,3 @@ public class StateMachineTests Assert.That(state3.ExitCalled, Is.False); } } - -/// -/// 测试状态类V2版本,实现IState接口用于测试 -/// -public sealed class TestStateV2 : IState -{ - public bool AllowTransition { get; set; } = true; - public bool EnterCalled { get; private set; } - public bool ExitCalled { get; private set; } - public int EnterCallCount { get; private set; } - public int ExitCallCount { get; private set; } - public IState? EnterFrom { get; private set; } - public IState? ExitTo { get; private set; } - - /// - /// 进入状态时的回调方法 - /// - /// 从哪个状态进入 - public void OnEnter(IState? from) - { - EnterCalled = true; - EnterCallCount++; - EnterFrom = from; - } - - /// - /// 离开状态时的回调方法 - /// - /// 离开到哪个状态 - public void OnExit(IState? to) - { - ExitCalled = true; - ExitCallCount++; - ExitTo = to; - } - - /// - /// 判断是否可以转换到目标状态 - /// - /// 目标状态 - /// 是否允许转换 - public bool CanTransitionTo(IState target) - { - return AllowTransition; - } -} - -/// -/// 测试状态类V3版本,实现IState接口用于测试 -/// -public sealed class TestStateV3 : IState -{ - public bool EnterCalled { get; private set; } - public bool ExitCalled { get; private set; } - public int EnterCallCount { get; private set; } - public int ExitCallCount { get; private set; } - public IState? EnterFrom { get; private set; } - public IState? ExitTo { get; private set; } - - /// - /// 进入状态时的回调方法 - /// - /// 从哪个状态进入 - public void OnEnter(IState? from) - { - EnterCalled = true; - EnterCallCount++; - EnterFrom = from; - } - - /// - /// 离开状态时的回调方法 - /// - /// 离开到哪个状态 - public void OnExit(IState? to) - { - ExitCalled = true; - ExitCallCount++; - ExitTo = to; - } - - /// - /// 判断是否可以转换到目标状态 - /// - /// 目标状态 - /// 是否允许转换 - public bool CanTransitionTo(IState target) - { - return true; - } -} - -/// -/// 测试状态类V4版本,实现IState接口用于测试 -/// -public sealed class TestStateV4 : IState -{ - public bool EnterCalled { get; private set; } - public bool ExitCalled { get; private set; } - public int EnterCallCount { get; private set; } - public int ExitCallCount { get; private set; } - public IState? EnterFrom { get; private set; } - public IState? ExitTo { get; private set; } - - /// - /// 进入状态时的回调方法 - /// - /// 从哪个状态进入 - public void OnEnter(IState? from) - { - EnterCalled = true; - EnterCallCount++; - EnterFrom = from; - } - - /// - /// 离开状态时的回调方法 - /// - /// 离开到哪个状态 - public void OnExit(IState? to) - { - ExitCalled = true; - ExitCallCount++; - ExitTo = to; - } - - /// - /// 判断是否可以转换到目标状态 - /// - /// 目标状态 - /// 是否允许转换 - public bool CanTransitionTo(IState target) - { - return true; - } -} - -/// -/// 异步测试状态类,同时实现IState和IAsyncState接口用于测试异步状态功能 -/// -public sealed class TestAsyncState : IState, IAsyncState -{ - public bool AllowTransition { get; set; } = true; - public bool EnterCalled { get; private set; } - public bool ExitCalled { get; private set; } - public int EnterCallCount { get; private set; } - public int ExitCallCount { get; private set; } - public IState? EnterFrom { get; private set; } - public IState? ExitTo { get; private set; } - public int CanTransitionToCallCount { get; private set; } - - /// - /// 异步进入状态时的回调方法 - /// - /// 从哪个状态进入 - public async Task OnEnterAsync(IState? from) - { - await Task.Delay(1).ConfigureAwait(false); - EnterCalled = true; - EnterCallCount++; - EnterFrom = from; - } - - /// - /// 异步离开状态时的回调方法 - /// - /// 离开到哪个状态 - public async Task OnExitAsync(IState? to) - { - await Task.Delay(1).ConfigureAwait(false); - ExitCalled = true; - ExitCallCount++; - ExitTo = to; - } - - /// - /// 异步判断是否可以转换到目标状态 - /// - /// 目标状态 - /// 是否允许转换 - public async Task CanTransitionToAsync(IState target) - { - await Task.Delay(1).ConfigureAwait(false); - CanTransitionToCallCount++; - return AllowTransition; - } - - /// - /// 进入状态时的回调方法(同步版本,抛出异常表示不应被调用) - /// - /// 从哪个状态进入 - public void OnEnter(IState? from) - { - throw new InvalidOperationException("Sync OnEnter should not be called for async state"); - } - - /// - /// 离开状态时的回调方法(同步版本,抛出异常表示不应被调用) - /// - /// 离开到哪个状态 - public void OnExit(IState? to) - { - throw new InvalidOperationException("Sync OnExit should not be called for async state"); - } - - /// - /// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用) - /// - /// 目标状态 - /// 是否允许转换 - public bool CanTransitionTo(IState target) - { - throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state"); - } -} - -/// -/// 状态机扩展方法类 -/// -public static class StateMachineExtensions -{ - /// - /// 检查状态机是否包含指定类型的状态 - /// - /// 要检查的状态类型 - /// 状态机实例 - /// 如果包含指定类型的状态则返回true,否则返回false - public static bool ContainsState(this StateMachine stateMachine) where T : IState - { - return stateMachine.GetType().GetField("States", BindingFlags.NonPublic | BindingFlags.Instance)? - .GetValue(stateMachine) is Dictionary states && - states.ContainsKey(typeof(T)); - } -} diff --git a/GFramework.Core.Tests/State/StateTests.cs b/GFramework.Core.Tests/State/StateTests.cs index d8ac2044..3feeb195 100644 --- a/GFramework.Core.Tests/State/StateTests.cs +++ b/GFramework.Core.Tests/State/StateTests.cs @@ -326,409 +326,3 @@ public class StateTests Assert.That(state.ExitCallCount, Is.EqualTo(2)); } } - -/// -/// 具体状态实现类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); - return AllowTransitions; - } -} - -/// -/// 具体状态实现类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; - } -} - -/// -/// 异步具体状态实现类V2版本,用于测试异步状态的基本功能 -/// -public sealed class ConcreteAsyncStateV2 : IState, IAsyncState -{ - /// - /// 获取或设置是否允许转换 - /// - public bool AllowTransitions { get; set; } = true; - - /// - /// 获取进入状态是否被调用的标志 - /// - public bool EnterCalled { get; private set; } - - /// - /// 获取退出状态是否被调用的标志 - /// - public bool ExitCalled { get; private set; } - - /// - /// 获取进入状态被调用的次数 - /// - public int EnterCallCount { get; private set; } - - /// - /// 获取退出状态被调用的次数 - /// - public int ExitCallCount { get; private set; } - - /// - /// 获取进入此状态的来源状态 - /// - public IState? EnterFrom { get; private set; } - - /// - /// 获取从此状态退出的目标状态 - /// - public IState? ExitTo { get; private set; } - - /// - /// 获取或设置转换到目标状态时执行的动作 - /// - public Action? CanTransitionToAsyncAction { get; set; } - - /// - /// 异步进入当前状态时调用的方法 - /// - /// 从哪个状态进入 - public async Task OnEnterAsync(IState? from) - { - await Task.Delay(1).ConfigureAwait(false); - EnterCalled = true; - EnterCallCount++; - EnterFrom = from; - } - - /// - /// 异步退出当前状态时调用的方法 - /// - /// 退出到哪个状态 - public async Task OnExitAsync(IState? to) - { - await Task.Delay(1).ConfigureAwait(false); - ExitCalled = true; - ExitCallCount++; - ExitTo = to; - } - - /// - /// 异步判断是否可以转换到目标状态 - /// - /// 目标状态 - /// 如果可以转换则返回true,否则返回false - public async Task CanTransitionToAsync(IState target) - { - await Task.Delay(1).ConfigureAwait(false); - CanTransitionToAsyncAction?.Invoke(target); - return AllowTransitions; - } - - /// - /// 进入当前状态时调用的方法(同步版本,抛出异常表示不应被调用) - /// - /// 从哪个状态进入 - public void OnEnter(IState? from) - { - throw new InvalidOperationException("Sync OnEnter should not be called for async state"); - } - - /// - /// 退出当前状态时调用的方法(同步版本,抛出异常表示不应被调用) - /// - /// 退出到哪个状态 - public void OnExit(IState? to) - { - throw new InvalidOperationException("Sync OnExit should not be called for async state"); - } - - /// - /// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用) - /// - /// 目标状态 - /// 如果可以转换则返回true,否则返回false - public bool CanTransitionTo(IState target) - { - throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state"); - } -} diff --git a/GFramework.Core.Tests/State/TestAsyncState.cs b/GFramework.Core.Tests/State/TestAsyncState.cs new file mode 100644 index 00000000..558afad3 --- /dev/null +++ b/GFramework.Core.Tests/State/TestAsyncState.cs @@ -0,0 +1,116 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供异步生命周期路径的测试状态。 +/// +public sealed class TestAsyncState : IState, IAsyncState +{ + /// + /// 获取或设置是否允许向目标状态转移。 + /// + public bool AllowTransitions { get; set; } = true; + + /// + /// 获取异步进入状态是否已被调用。 + /// + public bool EnterCalled { get; private set; } + + /// + /// 获取异步离开状态是否已被调用。 + /// + public bool ExitCalled { get; private set; } + + /// + /// 获取异步进入回调被调用的次数。 + /// + public int EnterCallCount { get; private set; } + + /// + /// 获取异步离开回调被调用的次数。 + /// + public int ExitCallCount { get; private set; } + + /// + /// 获取最近一次异步进入时的来源状态。 + /// + public IState? EnterFrom { get; private set; } + + /// + /// 获取最近一次异步离开时的目标状态。 + /// + public IState? ExitTo { get; private set; } + + /// + /// 获取异步转移检查被调用的次数。 + /// + public int CanTransitionToCallCount { get; private set; } + + /// + /// 异步记录进入状态的来源状态与调用次数。 + /// + /// 触发进入的来源状态。 + public async Task OnEnterAsync(IState? from) + { + await Task.Delay(1).ConfigureAwait(false); + EnterCalled = true; + EnterCallCount++; + EnterFrom = from; + } + + /// + /// 异步记录离开状态的目标状态与调用次数。 + /// + /// 即将切换到的目标状态。 + public async Task OnExitAsync(IState? to) + { + await Task.Delay(1).ConfigureAwait(false); + ExitCalled = true; + ExitCallCount++; + ExitTo = to; + } + + /// + /// 异步记录转移检查并返回当前是否允许切换。 + /// + /// 目标状态。 + /// 允许切换时返回 ,否则返回 + public async Task CanTransitionToAsync(IState target) + { + await Task.Delay(1).ConfigureAwait(false); + CanTransitionToCallCount++; + return AllowTransitions; + } + + /// + /// 同步进入入口不应被异步状态机路径调用。 + /// + /// 触发进入的来源状态。 + /// 总是抛出,表示当前测试状态只允许异步入口。 + public void OnEnter(IState? from) + { + throw new InvalidOperationException("Sync OnEnter should not be called for async state"); + } + + /// + /// 同步离开入口不应被异步状态机路径调用。 + /// + /// 即将切换到的目标状态。 + /// 总是抛出,表示当前测试状态只允许异步入口。 + public void OnExit(IState? to) + { + throw new InvalidOperationException("Sync OnExit should not be called for async state"); + } + + /// + /// 同步转移检查入口不应被异步状态机路径调用。 + /// + /// 目标状态。 + /// 此方法不会正常返回。 + /// 总是抛出,表示当前测试状态只允许异步入口。 + public bool CanTransitionTo(IState target) + { + throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state"); + } +} diff --git a/GFramework.Core.Tests/State/TestContextAwareStateV5.cs b/GFramework.Core.Tests/State/TestContextAwareStateV5.cs new file mode 100644 index 00000000..e5903d9d --- /dev/null +++ b/GFramework.Core.Tests/State/TestContextAwareStateV5.cs @@ -0,0 +1,26 @@ +using GFramework.Core.Abstractions.State; +using GFramework.Core.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供最小化的上下文感知状态实现。 +/// +public class TestContextAwareStateV5 : ContextAwareStateBase +{ + /// + /// 进入状态时调用。该测试替身不需要额外行为。 + /// + /// 前一个状态。 + public override void OnEnter(IState? previous) + { + } + + /// + /// 退出状态时调用。该测试替身不需要额外行为。 + /// + /// 下一个状态。 + public override void OnExit(IState? next) + { + } +} diff --git a/GFramework.Core.Tests/State/TestContextAwareStateV5_2.cs b/GFramework.Core.Tests/State/TestContextAwareStateV5_2.cs new file mode 100644 index 00000000..b810c479 --- /dev/null +++ b/GFramework.Core.Tests/State/TestContextAwareStateV5_2.cs @@ -0,0 +1,26 @@ +using GFramework.Core.Abstractions.State; +using GFramework.Core.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供第二个可区分类型的上下文感知状态实现。 +/// +public class TestContextAwareStateV5_2 : ContextAwareStateBase +{ + /// + /// 进入状态时调用。该测试替身不需要额外行为。 + /// + /// 前一个状态。 + public override void OnEnter(IState? previous) + { + } + + /// + /// 退出状态时调用。该测试替身不需要额外行为。 + /// + /// 下一个状态。 + public override void OnExit(IState? next) + { + } +} diff --git a/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs b/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs new file mode 100644 index 00000000..9b80dfd6 --- /dev/null +++ b/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using GFramework.Core.Abstractions.State; +using GFramework.Core.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供可观察内部状态注册表的测试状态机实现。 +/// +public class TestStateMachineSystemV5 : StateMachineSystem +{ + /// + /// 获取状态机当前维护的状态实例映射,供测试断言注册结果使用。 + /// + /// 状态类型到状态实例的只读视图。 + public IReadOnlyDictionary GetStates() + { + return States as IReadOnlyDictionary ?? new ReadOnlyDictionary(States); + } +} diff --git a/GFramework.Core.Tests/State/TestStateV2.cs b/GFramework.Core.Tests/State/TestStateV2.cs new file mode 100644 index 00000000..2d2f26d2 --- /dev/null +++ b/GFramework.Core.Tests/State/TestStateV2.cs @@ -0,0 +1,76 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供可配置转移结果的同步测试状态。 +/// +public sealed class TestStateV2 : IState +{ + /// + /// 获取或设置是否允许向目标状态转移。 + /// + public bool AllowTransition { get; set; } = true; + + /// + /// 获取进入状态是否已被调用。 + /// + public bool EnterCalled { get; private set; } + + /// + /// 获取离开状态是否已被调用。 + /// + public bool ExitCalled { get; private set; } + + /// + /// 获取进入回调被调用的次数。 + /// + public int EnterCallCount { get; private set; } + + /// + /// 获取离开回调被调用的次数。 + /// + public int ExitCallCount { get; private set; } + + /// + /// 获取最近一次进入时的来源状态。 + /// + public IState? EnterFrom { get; private set; } + + /// + /// 获取最近一次离开时的目标状态。 + /// + public IState? ExitTo { get; private set; } + + /// + /// 记录进入状态时的来源状态与调用次数。 + /// + /// 触发进入的来源状态。 + public void OnEnter(IState? from) + { + EnterCalled = true; + EnterCallCount++; + EnterFrom = from; + } + + /// + /// 记录离开状态时的目标状态与调用次数。 + /// + /// 即将切换到的目标状态。 + public void OnExit(IState? to) + { + ExitCalled = true; + ExitCallCount++; + ExitTo = to; + } + + /// + /// 根据 返回是否允许切换。 + /// + /// 目标状态。 + /// 允许切换时返回 ,否则返回 + public bool CanTransitionTo(IState target) + { + return AllowTransition; + } +} diff --git a/GFramework.Core.Tests/State/TestStateV3.cs b/GFramework.Core.Tests/State/TestStateV3.cs new file mode 100644 index 00000000..9bb05e4c --- /dev/null +++ b/GFramework.Core.Tests/State/TestStateV3.cs @@ -0,0 +1,71 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供始终允许切换的同步测试状态。 +/// +public sealed class TestStateV3 : IState +{ + /// + /// 获取进入状态是否已被调用。 + /// + public bool EnterCalled { get; private set; } + + /// + /// 获取离开状态是否已被调用。 + /// + public bool ExitCalled { get; private set; } + + /// + /// 获取进入回调被调用的次数。 + /// + public int EnterCallCount { get; private set; } + + /// + /// 获取离开回调被调用的次数。 + /// + public int ExitCallCount { get; private set; } + + /// + /// 获取最近一次进入时的来源状态。 + /// + public IState? EnterFrom { get; private set; } + + /// + /// 获取最近一次离开时的目标状态。 + /// + public IState? ExitTo { get; private set; } + + /// + /// 记录进入状态时的来源状态与调用次数。 + /// + /// 触发进入的来源状态。 + public void OnEnter(IState? from) + { + EnterCalled = true; + EnterCallCount++; + EnterFrom = from; + } + + /// + /// 记录离开状态时的目标状态与调用次数。 + /// + /// 即将切换到的目标状态。 + public void OnExit(IState? to) + { + ExitCalled = true; + ExitCallCount++; + ExitTo = to; + } + + /// + /// 始终允许切换到目标状态。 + /// + /// 目标状态。 + /// 始终返回 + public bool CanTransitionTo(IState target) + { + return true; + } +} diff --git a/GFramework.Core.Tests/State/TestStateV4.cs b/GFramework.Core.Tests/State/TestStateV4.cs new file mode 100644 index 00000000..50788354 --- /dev/null +++ b/GFramework.Core.Tests/State/TestStateV4.cs @@ -0,0 +1,71 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 保留的附加同步测试状态实现。 +/// +public sealed class TestStateV4 : IState +{ + /// + /// 获取进入状态是否已被调用。 + /// + public bool EnterCalled { get; private set; } + + /// + /// 获取离开状态是否已被调用。 + /// + public bool ExitCalled { get; private set; } + + /// + /// 获取进入回调被调用的次数。 + /// + public int EnterCallCount { get; private set; } + + /// + /// 获取离开回调被调用的次数。 + /// + public int ExitCallCount { get; private set; } + + /// + /// 获取最近一次进入时的来源状态。 + /// + public IState? EnterFrom { get; private set; } + + /// + /// 获取最近一次离开时的目标状态。 + /// + public IState? ExitTo { get; private set; } + + /// + /// 记录进入状态时的来源状态与调用次数。 + /// + /// 触发进入的来源状态。 + public void OnEnter(IState? from) + { + EnterCalled = true; + EnterCallCount++; + EnterFrom = from; + } + + /// + /// 记录离开状态时的目标状态与调用次数。 + /// + /// 即将切换到的目标状态。 + public void OnExit(IState? to) + { + ExitCalled = true; + ExitCallCount++; + ExitTo = to; + } + + /// + /// 始终允许切换到目标状态。 + /// + /// 目标状态。 + /// 始终返回 + public bool CanTransitionTo(IState target) + { + return true; + } +} diff --git a/GFramework.Core.Tests/State/TestStateV5.cs b/GFramework.Core.Tests/State/TestStateV5.cs new file mode 100644 index 00000000..64aee177 --- /dev/null +++ b/GFramework.Core.Tests/State/TestStateV5.cs @@ -0,0 +1,40 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供最小化的普通状态实现。 +/// +public class TestStateV5 : IState +{ + /// + /// 获取或设置测试状态标识符。 + /// + public int Id { get; set; } + + /// + /// 判断是否允许转换到下一个状态。 + /// + /// 目标状态。 + /// 始终返回 以简化状态机切换测试。 + public bool CanTransitionTo(IState next) + { + return true; + } + + /// + /// 进入状态时调用。该测试替身不需要额外行为。 + /// + /// 前一个状态。 + public void OnEnter(IState? previous) + { + } + + /// + /// 退出状态时调用。该测试替身不需要额外行为。 + /// + /// 下一个状态。 + public void OnExit(IState? next) + { + } +} diff --git a/GFramework.Core.Tests/State/TestStateV5_2.cs b/GFramework.Core.Tests/State/TestStateV5_2.cs new file mode 100644 index 00000000..190864ce --- /dev/null +++ b/GFramework.Core.Tests/State/TestStateV5_2.cs @@ -0,0 +1,43 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 为 提供第二个可区分类型的普通状态实现。 +/// +public class TestStateV5_2 : IState +{ + /// + /// 获取或设置测试状态标识符。 + /// + public int Id { get; set; } + + /// + /// 判断是否允许转换到下一个状态。 + /// + /// 目标状态。 + /// 始终返回 以简化状态机切换测试。 + public bool CanTransitionTo(IState next) + { + _ = next; + return true; + } + + /// + /// 进入状态时调用。该测试替身不需要额外行为。 + /// + /// 前一个状态。 + public void OnEnter(IState? previous) + { + _ = previous; + } + + /// + /// 退出状态时调用。该测试替身不需要额外行为。 + /// + /// 下一个状态。 + public void OnExit(IState? next) + { + _ = next; + } +} diff --git a/GFramework.Core.Tests/State/TrackingStateV2.cs b/GFramework.Core.Tests/State/TrackingStateV2.cs new file mode 100644 index 00000000..0bd5cab3 --- /dev/null +++ b/GFramework.Core.Tests/State/TrackingStateV2.cs @@ -0,0 +1,59 @@ +using GFramework.Core.Abstractions.State; + +namespace GFramework.Core.Tests.State; + +/// +/// 跟踪状态实现类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; + } + + /// + /// 判断是否可以转换到目标状态。 + /// + /// 目标状态。 + /// 始终返回 + public bool CanTransitionTo(IState target) + { + return true; + } +} diff --git a/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs b/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs index 9fcdc0bb..da01d06a 100644 --- a/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs +++ b/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs @@ -1,4 +1,3 @@ -using GFramework.Core.Abstractions.Logging; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Utility; using GFramework.Core.Architectures; @@ -199,7 +198,7 @@ public class AbstractContextUtilityTests Assert.That(utility.Destroyed, Is.True); // 重置状态 - utility.Destroyed = false; + utility.ResetDestroyedStateForTest(); // 第二次初始化和销毁 utility.Initialize(); @@ -208,87 +207,3 @@ public class AbstractContextUtilityTests Assert.That(utility.Destroyed, Is.True); } } - -/// -/// 测试用上下文工具类V1 -/// -public sealed class TestContextUtilityV1 : AbstractContextUtility -{ - /// - /// 获取工具是否已初始化 - /// - public bool Initialized { get; private set; } - - /// - /// 获取工具是否已销毁 - /// - public bool Destroyed { get; set; } - - /// - /// 获取Init方法是否被调用 - /// - public bool InitCalled { get; private set; } - - /// - /// 获取Logger对象(用于测试) - /// - public ILogger? GetLogger() - { - return Logger; - } - - /// - /// 初始化方法 - /// - protected override void OnInit() - { - Initialized = true; - InitCalled = true; - } - - /// - /// 销毁方法 - /// - protected override void OnDestroy() - { - Destroyed = true; - } -} - -/// -/// 测试用上下文工具类V2,自定义初始化逻辑 -/// -public sealed class TestContextUtilityV2 : AbstractContextUtility -{ - /// - /// 获取工具是否已初始化 - /// - public bool Initialized { get; private set; } - - /// - /// 获取工具是否已销毁 - /// - public bool Destroyed { get; set; } - - /// - /// 获取自定义初始化是否完成 - /// - public bool CustomInitializationDone { get; private set; } - - /// - /// 初始化方法(自定义逻辑) - /// - protected override void OnInit() - { - Initialized = true; - CustomInitializationDone = true; - } - - /// - /// 销毁方法 - /// - protected override void OnDestroy() - { - Destroyed = true; - } -} \ No newline at end of file diff --git a/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs b/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs new file mode 100644 index 00000000..9140ee72 --- /dev/null +++ b/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs @@ -0,0 +1,60 @@ +using GFramework.Core.Abstractions.Logging; +using GFramework.Core.Utility; + +namespace GFramework.Core.Tests.Utility; + +/// +/// 为 提供的基础上下文工具测试桩。 +/// +public sealed class TestContextUtilityV1 : AbstractContextUtility +{ + /// + /// 获取一个值,该值指示当前工具是否已完成初始化。 + /// + public bool Initialized { get; private set; } + + /// + /// 获取一个值,该值指示当前工具是否已执行销毁逻辑。 + /// + public bool Destroyed { get; private set; } + + /// + /// 获取一个值,该值指示测试专用的 钩子是否已被调用。 + /// 该标记与 共享同一执行时机,但单独暴露以便断言钩子本身已运行。 + /// + public bool InitCalled { get; private set; } + + /// + /// 获取初始化阶段创建的日志记录器,供测试断言使用。 + /// + /// 初始化后缓存的日志记录器;初始化前返回 + public ILogger? GetLogger() + { + return Logger; + } + + /// + /// 记录初始化已发生,并标记测试钩子调用状态。 + /// + protected override void OnInit() + { + Initialized = true; + InitCalled = true; + } + + /// + /// 记录销毁流程已运行,供生命周期测试断言使用。 + /// + protected override void OnDestroy() + { + Destroyed = true; + } + + /// + /// 重置销毁标记,供同一实例的重复生命周期测试在下一轮初始化前清理观测状态。 + /// + public void ResetDestroyedStateForTest() + { + Destroyed = false; + } +} diff --git a/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs b/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs new file mode 100644 index 00000000..d52d7067 --- /dev/null +++ b/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs @@ -0,0 +1,41 @@ +using GFramework.Core.Utility; + +namespace GFramework.Core.Tests.Utility; + +/// +/// 为 提供的自定义初始化上下文工具测试桩。 +/// +public sealed class TestContextUtilityV2 : AbstractContextUtility +{ + /// + /// 获取一个值,该值指示当前工具是否已完成初始化。 + /// + public bool Initialized { get; private set; } + + /// + /// 获取一个值,该值指示当前工具是否已执行销毁逻辑。 + /// + public bool Destroyed { get; private set; } + + /// + /// 获取一个值,该值指示自定义初始化步骤是否已完成。 + /// + public bool CustomInitializationDone { get; private set; } + + /// + /// 在基础初始化期间记录自定义初始化步骤已执行。 + /// + protected override void OnInit() + { + Initialized = true; + CustomInitializationDone = true; + } + + /// + /// 记录销毁流程已运行,供生命周期测试断言使用。 + /// + protected override void OnDestroy() + { + Destroyed = true; + } +} diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md index 55ad6417..13d194c0 100644 --- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md +++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md @@ -6,21 +6,28 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-084` -- 当前阶段:`Phase 84` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-086` +- 当前阶段:`Phase 86` - 当前焦点: - - `2026-04-27` 已完成 PR `#297` 的 CodeRabbit follow-up,修复 `YamlConfigLoader` 的取消语义与 `IntegerTryParseDelegate` 可空性问题 - - 已补齐 `GFramework.Core.Tests/Ioc` 与 `GFramework.Core.Tests/Query` 中 review 指向的 XML 文档缺口,并让 `IPrioritizedService` 复用 `IMixedService.Name` 契约 - - 已新增 `YamlConfigLoaderTests` 回归测试,锁定“取消时保留 `OperationCanceledException`”这一行为 - - 当前分支的下一波 warning reduction 仍建议回到 `ArchitectureContextTests.cs`、`AsyncQueryExecutorTests.cs` 或 `YamlConfigSchemaValidator*` 的后续 slice + - `2026-04-27` 已按 `$gframework-batch-boot 100` 连续执行多波 `MA0048` 小切片,当前以 `GFramework.Core.Tests` 的测试辅助类型拆分为主 + - `2026-04-27` 已按 `$gframework-pr-review` 收敛 `PR #298` 的有效 nitpick,修复测试辅助类型的只读暴露、线程安全、空安全与文档一致性问题 + - 本轮已完成 `ArchitectureContextTests`、`AsyncQueryExecutorTests`、`CommandExecutorTests`、`StateTests`、`StateMachineTests`、`StateMachineSystemTests`、`ArchitectureModulesBehaviorTests`、`ArchitectureAdditionalCqrsHandlersTests`、`QueryCoroutineExtensionsTests`、`ObjectPoolTests`、`AbstractContextUtilityTests` 等低风险单文件切片 + - 当前仓库根权威基线已从 `353 Warning(s)` / `279` 个唯一位点下降到 `288 Warning(s)` / `214` 个唯一位点 + - 当前分支下一波更适合转向 `GameContextTests.cs`、`ArchitectureServicesTests.cs`、`RegistryInitializationHookBaseTests.cs` 这类仍在 `GFramework.Core.Tests` 内、但已混入 `CS8766` / `MA0016` 的小型混合切片 ## 当前活跃事实 -- 当前 `origin/main` 基线提交为 `b6a9fef`(`2026-04-27T10:53:34+08:00`)。 +- 当前 `origin/main` 基线提交为 `7cfdd2c`(`2026-04-27T16:59:57+08:00`)。 - 当前直接验证结果: - - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - - 最新结果:成功;`0 Warning(s)`、`0 Error(s)` - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 最新结果:成功;`28 Warning(s)`、`0 Error(s)`;当前 warning 来自 `GameContextTests.cs`、`ArchitectureServicesTests.cs`、`RegistryInitializationHookBaseTests.cs` 等既有热点 + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build` + - 最新结果:成功;`1610` 通过、`0` 失败 + - `dotnet clean` + - 最新结果:成功;已刷新仓库根 non-incremental 基线 + - `dotnet build` + - 最新结果:成功;`288 Warning(s)`、`0 Error(s)`,唯一位点 `214` + - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 最新结果:成功;`0 Warning(s)`、`0 Error(s)` - `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderTests.ReadYamlAsync_Should_Preserve_OperationCanceledException_When_Cancellation_Is_Requested"` - 最新结果:成功;`1` 通过、`0` 失败 @@ -29,18 +36,21 @@ - `dotnet format GFramework.sln --verify-no-changes --include GFramework.Game/Config/YamlConfigLoader.cs GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs GFramework.Core.Tests/Ioc/IMixedService.cs GFramework.Core.Tests/Ioc/IPrioritizedService.cs GFramework.Core.Tests/Ioc/PrioritizedService.cs GFramework.Core.Tests/Query/TestAsyncQueryWithExceptionV4.cs` - 最新结果:成功;本次 PR follow-up 改动文件无需额外格式化 - 当前批次摘要: - - 本轮完成 PR `#297` 最新 head review 中仍然有效的 `3` 个 open threads 修复:`YamlConfigLoader` 取消语义、`IMixedService.Name` XML 文档、`IPrioritizedService` 相关契约整理 - - 本轮同时吸收 CodeRabbit folded nitpick 中仍然成立的 `2` 个点:`IntegerTryParseDelegate` 可空性对齐、`TestAsyncQueryWithExceptionV4.OnDoAsync` 的 `` 文档 - - 本轮新增一条精确回归测试,确保底层 YAML 文件读取在取消时继续抛出 `OperationCanceledException` 系列异常,而不是包装成 `ConfigLoadException` + - 本轮通过多批并行 worker 共完成 `20+` 个 `GFramework.Core.Tests` 文件的测试辅助类型拆分,集中消化纯 `MA0048` warning 热点 + - 本轮停止时共享工作树共有 `61` 个变更条目,仍低于 `$gframework-batch-boot 100` 的文件停止线 + - 本轮仓库根权威 warning 已从开始时的 `353` 下降到 `288`,且 `GFramework.Core.Tests` 受影响项目的 Release 构建已恢复到 `0 Warning(s)` / `0 Error(s)` - 当前建议保留到下一波次的候选: - - `GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs` 的 `7` 个 `MA0048` - - `GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs` 的 `7` 个 `MA0048` + - `GFramework.Core.Tests/Architectures/GameContextTests.cs` 的 `4` 个 `CS8766` 与 `2` 个 `MA0048` + - `GFramework.Core.Tests/Architectures/ArchitectureServicesTests.cs` 的 `4` 个 `CS8766` 与 `1` 个 `MA0048` + - `GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs` 的 `1` 个 `MA0016` 与 `5` 个 `MA0048` - `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 与 `YamlConfigSchemaValidator.ObjectKeywords.cs` 的高耦合 warning 热点 ## 当前风险 - `GFramework.Cqrs.Tests/Mediator/*` 仍有 `47` / `44` / `34` 个唯一 warning 位点,属于高 changed-file 风险的 `MA0048` 大波次。 - 缓解措施:优先继续处理 `6-7` 个 warning 的小文件切片,避免一次性推高文件数。 +- `GameContextTests.cs`、`ArchitectureServicesTests.cs` 这类混合 `CS8766` / `MA0048` 文件不再适合继续用“纯拆分”模式批量下发。 + - 缓解措施:下一波由主线程先局部修正可空签名,再决定是否继续并行拆分。 - `YamlConfigSchemaValidator*` 仍然聚集多类高耦合 warning。 - 缓解措施:继续把它们留在独立波次,不与测试项目的低风险拆分混提。 @@ -67,6 +77,6 @@ ## 下一步建议 -1. 提交本轮 PR `#297` review follow-up 与 `ai-plan` 同步。 -2. 下一波优先挑选 `ArchitectureContextTests.cs` 或 `AsyncQueryExecutorTests.cs` 这类 `7`-warning 的纯 `MA0048` 单文件切片。 +1. 提交本轮多批 `MA0048` warning reduction 与 `ai-plan` 同步。 +2. 下一波由主线程先处理 `GameContextTests.cs` / `ArchitectureServicesTests.cs` 的 `CS8766`,再决定是否继续拆分剩余 `MA0048`。 3. 继续将 `YamlConfigSchemaValidator*` 与 `GFramework.Cqrs.Tests/Mediator/*` 作为独立高风险波次处理。 diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md index 20ac885c..b57f4b67 100644 --- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md +++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md @@ -1,5 +1,73 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-27 — RP-086 + +### 阶段:收敛 PR #298 的 CodeRabbit nitpick follow-up + +- 触发背景: + - 用户再次执行 `$gframework-pr-review` 后,要求按 `PR #298` 的 nitpick comments 收敛仍然适用的问题 + - 复核 PR 真值后确认当前分支无 failed checks、无 open review threads,但仍有一批测试辅助类型的可维护性 nitpick 值得本地落地 +- 主线程实施: + - 校验 `TestStateMachineSystemV5`、`ComplexQuery`、`TrackingPipelineBehavior`、`TestEnvironment`、`TestContextUtilityV1/V2` 等改动后,分别修复可变内部状态暴露、`_context!` 空抑制、静态计数器非原子递增、`new Register(...)` 测试辅助入口和生命周期标记公开 setter 问题 + - 统一更新 `TestQueryV2`、`TestCommandWithResultV2`、`TestAsyncQueryInput`、`TestAsyncQueryResult*` 的 XML 文档,使 `init` 属性语义与文档一致 + - 将三倍结果属性从 `DoubleValue` 更名为 `TripleValue`,同步更新 `TestAsyncComplexQuery*` 与相关断言,避免名称与 `* 3` 的行为不一致 + - 精简 active tracking,移除重复的 `GFramework.Core.Tests` Release build 记录,并把该项目的当前真值修正为 `28 Warning(s)` +- 验证里程碑: + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`28 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build` + - 结果:成功;`1610` 通过、`0` 失败 +- 当前结论: + - `PR #298` 中仍然适用的低风险 nitpick 已完成收敛,且没有为当前 touched files 引入新的构建 warning 或测试回归 + - `GFramework.Core.Tests` 的剩余 warning 仍集中在 `GameContextTests.cs`、`ArchitectureServicesTests.cs`、`RegistryInitializationHookBaseTests.cs` 等既有热点,不属于本轮 nitpick follow-up 新引入问题 +- 下一步: + 1. 提交本轮 `PR #298` nitpick follow-up 与 `ai-plan` 同步。 + 2. 回到 `GameContextTests.cs` / `ArchitectureServicesTests.cs` 的 `CS8766` warning reduction 主线。 + +## 2026-04-27 — RP-085 + +### 阶段:按 `$gframework-batch-boot 100` 并行消化 `GFramework.Core.Tests` 低风险 `MA0048` + +- 触发背景: + - 用户要求以仓库根 non-incremental 构建 warning 为准,并在上下文可控前提下把小切片分派给多个 subagent 并行处理 + - 本轮开始时,当前分支与 `origin/main@7cfdd2c` 无提交差异,适合从纯 `MA0048` 单文件切片起步 +- 主线程实施: + - 执行权威基线:`dotnet clean` + 仓库根 `dotnet build` + - 初始结果:`353 Warning(s)`、唯一位点 `279` + - 分四波次并行下发 `GFramework.Core.Tests` 小切片,累计完成 `20+` 个文件的测试辅助类型拆分 + - 主线程持续复核共享工作树、处理并发编译阻断,并在每一轮后复跑 `GFramework.Core.Tests` Release 构建 + - 在工作树达到 `61` 个变更条目时主动停止扩批,保留对 `100` 文件停止线的充分余量 +- 代表性已落地切片: + - `ArchitectureContextTests.cs` + - `AsyncQueryExecutorTests.cs` + - `CommandExecutorTests.cs` + - `StateTests.cs` + - `StateMachineTests.cs` + - `StateMachineSystemTests.cs` + - `ArchitectureModulesBehaviorTests.cs` + - `ArchitectureAdditionalCqrsHandlersTests.cs` + - `QueryCoroutineExtensionsTests.cs` + - `ObjectPoolTests.cs` + - `AbstractContextUtilityTests.cs` + - `EnvironmentTests.cs` + - `EventBusTests.cs` + - `ContextAwareTests.cs` +- 验证里程碑: + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`0 Warning(s)`、`0 Error(s)` + - `dotnet clean` + - 结果:成功 + - `dotnet build` + - 结果:成功;`288 Warning(s)`、`0 Error(s)`,唯一位点 `214` +- 当前结论: + - 本轮主要收益来自 `GFramework.Core.Tests` 内的纯 `MA0048` 大范围收敛 + - 仓库根权威 warning 已从 `353` 降到 `288`,唯一位点从 `279` 降到 `214` + - 下一波不再适合继续盲目平铺纯拆分,因为剩余 `GFramework.Core.Tests` 热点已开始混入 `CS8766` / `MA0016` +- 下一步: + 1. 提交本轮 warning reduction 与 `ai-plan` 同步。 + 2. 下一波优先由主线程处理 `GameContextTests.cs` / `ArchitectureServicesTests.cs` 的混合 warning。 + 3. 保持 `YamlConfigSchemaValidator*` 与 `GFramework.Cqrs.Tests/Mediator/*` 为独立高风险波次。 + ## 2026-04-27 — RP-084 ### 阶段:收敛 PR #297 的 CodeRabbit follow-up