mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
Merge pull request #298 from GeWuYou/fix/analyzer-warning-reduction-batch
Fix/analyzer warning reduction batch
This commit is contained in:
commit
6cc87a9f6c
@ -0,0 +1,8 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 用于验证额外程序集接入是否成功的测试通知。
|
||||
/// </summary>
|
||||
public sealed record AdditionalAssemblyNotification : INotification;
|
||||
@ -0,0 +1,46 @@
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
using GFramework.Cqrs;
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟由 source-generator 为扩展程序集生成的 CQRS handler registry。
|
||||
/// </summary>
|
||||
internal sealed class AdditionalAssemblyNotificationHandlerRegistry : ICqrsHandlerRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// 将扩展程序集中的通知处理器映射写入服务集合。
|
||||
/// </summary>
|
||||
/// <param name="services">目标服务集合。</param>
|
||||
/// <param name="logger">日志记录器。</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="services" /> 或 <paramref name="logger" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
public void Register(IServiceCollection services, ILogger logger)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(services);
|
||||
ArgumentNullException.ThrowIfNull(logger);
|
||||
|
||||
services.AddTransient<INotificationHandler<AdditionalAssemblyNotification>>(_ => CreateHandler());
|
||||
logger.Debug(
|
||||
$"Registered CQRS handler proxy for {typeof(INotificationHandler<AdditionalAssemblyNotification>).FullName}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个仅供显式程序集注册路径使用的动态通知处理器。
|
||||
/// </summary>
|
||||
/// <returns>用于记录通知触发次数的测试替身处理器。</returns>
|
||||
private static INotificationHandler<AdditionalAssemblyNotification> CreateHandler()
|
||||
{
|
||||
var handler = new Mock<INotificationHandler<AdditionalAssemblyNotification>>();
|
||||
handler
|
||||
.Setup(target => target.Handle(It.IsAny<AdditionalAssemblyNotification>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
AdditionalAssemblyNotificationHandlerState.RecordInvocation();
|
||||
return ValueTask.CompletedTask;
|
||||
});
|
||||
return handler.Object;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 记录模拟扩展程序集通知处理器的执行次数。
|
||||
/// </summary>
|
||||
public static class AdditionalAssemblyNotificationHandlerState
|
||||
{
|
||||
private static int _invocationCount;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前测试进程中该处理器的执行次数。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该计数器通过原子读写维护,以支持 NUnit 并行执行环境中的并发访问。
|
||||
/// </remarks>
|
||||
public static int InvocationCount => Volatile.Read(ref _invocationCount);
|
||||
|
||||
/// <summary>
|
||||
/// 记录一次通知处理,供测试断言显式程序集接入后的运行时行为。
|
||||
/// </summary>
|
||||
public static void RecordInvocation()
|
||||
{
|
||||
Interlocked.Increment(ref _invocationCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理共享计数器,避免测试间相互污染。
|
||||
/// </summary>
|
||||
public static void Reset()
|
||||
{
|
||||
Interlocked.Exchange(ref _invocationCount, 0);
|
||||
}
|
||||
}
|
||||
@ -121,88 +121,3 @@ public sealed class ArchitectureAdditionalCqrsHandlersTests
|
||||
return architecture;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于验证额外程序集接入是否成功的测试通知。
|
||||
/// </summary>
|
||||
public sealed record AdditionalAssemblyNotification : INotification;
|
||||
|
||||
/// <summary>
|
||||
/// 记录模拟扩展程序集通知处理器的执行次数。
|
||||
/// </summary>
|
||||
public static class AdditionalAssemblyNotificationHandlerState
|
||||
{
|
||||
private static int _invocationCount;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前测试进程中该处理器的执行次数。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该计数器通过原子读写维护,以支持 NUnit 并行执行环境中的并发访问。
|
||||
/// </remarks>
|
||||
public static int InvocationCount => Volatile.Read(ref _invocationCount);
|
||||
|
||||
/// <summary>
|
||||
/// 记录一次通知处理,供测试断言显式程序集接入后的运行时行为。
|
||||
/// </summary>
|
||||
public static void RecordInvocation()
|
||||
{
|
||||
Interlocked.Increment(ref _invocationCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理共享计数器,避免测试间相互污染。
|
||||
/// </summary>
|
||||
public static void Reset()
|
||||
{
|
||||
Interlocked.Exchange(ref _invocationCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟由 source-generator 为扩展程序集生成的 CQRS handler registry。
|
||||
/// </summary>
|
||||
internal sealed class AdditionalAssemblyNotificationHandlerRegistry : ICqrsHandlerRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// 将扩展程序集中的通知处理器映射写入服务集合。
|
||||
/// </summary>
|
||||
/// <param name="services">目标服务集合。</param>
|
||||
/// <param name="logger">日志记录器。</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// 当 <paramref name="services" /> 或 <paramref name="logger" /> 为 <see langword="null" /> 时抛出。
|
||||
/// </exception>
|
||||
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<INotificationHandler<AdditionalAssemblyNotification>>(_ => CreateHandler());
|
||||
logger.Debug(
|
||||
$"Registered CQRS handler proxy for {typeof(INotificationHandler<AdditionalAssemblyNotification>).FullName}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个仅供显式程序集注册路径使用的动态通知处理器。
|
||||
/// </summary>
|
||||
/// <returns>用于记录通知触发次数的测试替身处理器。</returns>
|
||||
private static INotificationHandler<AdditionalAssemblyNotification> CreateHandler()
|
||||
{
|
||||
var handler = new Mock<INotificationHandler<AdditionalAssemblyNotification>>();
|
||||
handler
|
||||
.Setup(target => target.Handle(It.IsAny<AdditionalAssemblyNotification>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() =>
|
||||
{
|
||||
AdditionalAssemblyNotificationHandlerState.RecordInvocation();
|
||||
return ValueTask.CompletedTask;
|
||||
});
|
||||
return handler.Object;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<int>
|
||||
{
|
||||
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<int>
|
||||
{
|
||||
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
|
||||
|
||||
@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于验证管道行为注册是否生效的测试请求。
|
||||
/// </summary>
|
||||
public sealed class ModuleBehaviorRequest : IRequest<string>
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理测试请求的处理器。
|
||||
/// </summary>
|
||||
public sealed class ModuleBehaviorRequestHandler : IRequestHandler<ModuleBehaviorRequest, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回固定结果,便于聚焦验证管道行为是否执行。
|
||||
/// </summary>
|
||||
/// <param name="request">请求实例。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>固定响应内容。</returns>
|
||||
public ValueTask<string> Handle(ModuleBehaviorRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
return ValueTask.FromResult("handled");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录请求通过管道次数的测试行为。
|
||||
/// </summary>
|
||||
/// <typeparam name="TRequest">请求类型。</typeparam>
|
||||
/// <typeparam name="TResponse">响应类型。</typeparam>
|
||||
public sealed class TrackingPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前测试进程中该请求类型对应的行为触发次数。
|
||||
/// </summary>
|
||||
public static int InvocationCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 记录一次行为执行,然后继续执行下一个处理器。
|
||||
/// </summary>
|
||||
/// <param name="message">当前请求消息。</param>
|
||||
/// <param name="next">下一个处理委托。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>下游处理器的响应结果。</returns>
|
||||
public async ValueTask<TResponse> Handle(
|
||||
TRequest message, MessageHandlerDelegate<TRequest, TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
InvocationCount++;
|
||||
return await next(message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
10
GFramework.Core.Tests/Architectures/ModuleBehaviorRequest.cs
Normal file
10
GFramework.Core.Tests/Architectures/ModuleBehaviorRequest.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 用于验证管道行为注册是否生效的测试请求。
|
||||
/// </summary>
|
||||
public sealed class ModuleBehaviorRequest : IRequest<string>
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 处理测试请求的处理器。
|
||||
/// </summary>
|
||||
public sealed class ModuleBehaviorRequestHandler : IRequestHandler<ModuleBehaviorRequest, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回固定结果,便于聚焦验证管道行为是否执行。
|
||||
/// </summary>
|
||||
/// <param name="request">请求实例。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>固定响应内容。</returns>
|
||||
public ValueTask<string> Handle(ModuleBehaviorRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
return ValueTask.FromResult("handled");
|
||||
}
|
||||
}
|
||||
43
GFramework.Core.Tests/Architectures/TestCommandV2.cs
Normal file
43
GFramework.Core.Tests/Architectures/TestCommandV2.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的测试命令桩。
|
||||
/// </summary>
|
||||
public sealed class TestCommandV2 : ICommand
|
||||
{
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令,并记录执行状态。
|
||||
/// </summary>
|
||||
public void Execute()
|
||||
{
|
||||
Executed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关联当前命令所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">要保存的架构上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前命令已绑定的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>测试期间保存的架构上下文。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的带返回值测试命令桩。
|
||||
/// </summary>
|
||||
public sealed class TestCommandWithResultV2 : ICommand<int>
|
||||
{
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令执行结果;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Result { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令并返回预设结果。
|
||||
/// </summary>
|
||||
/// <returns>测试预设的命令结果。</returns>
|
||||
public int Execute()
|
||||
{
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关联当前命令所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">要保存的架构上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前命令已绑定的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>测试期间保存的架构上下文。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
}
|
||||
12
GFramework.Core.Tests/Architectures/TestEventV2.cs
Normal file
12
GFramework.Core.Tests/Architectures/TestEventV2.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的测试事件载荷。
|
||||
/// </summary>
|
||||
public sealed class TestEventV2
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置测试事件数据。
|
||||
/// </summary>
|
||||
public int Data { get; init; }
|
||||
}
|
||||
58
GFramework.Core.Tests/Architectures/TestModelV2.cs
Normal file
58
GFramework.Core.Tests/Architectures/TestModelV2.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Enums;
|
||||
using GFramework.Core.Abstractions.Model;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的测试模型桩。
|
||||
/// </summary>
|
||||
public sealed class TestModelV2 : IModel
|
||||
{
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置测试用标识。
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联当前模型所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">要保存的架构上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前模型已绑定的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>测试期间保存的架构上下文。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化测试模型。
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收架构阶段切换通知。
|
||||
/// </summary>
|
||||
/// <param name="phase">当前架构阶段。</param>
|
||||
public void OnArchitecturePhase(ArchitecturePhase phase)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁测试模型。
|
||||
/// </summary>
|
||||
public void Destroy()
|
||||
{
|
||||
}
|
||||
}
|
||||
44
GFramework.Core.Tests/Architectures/TestQueryV2.cs
Normal file
44
GFramework.Core.Tests/Architectures/TestQueryV2.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的测试查询桩。
|
||||
/// </summary>
|
||||
public sealed class TestQueryV2 : IQuery<int>
|
||||
{
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取查询返回值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Result { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询并返回预设结果。
|
||||
/// </summary>
|
||||
/// <returns>测试预设的查询结果。</returns>
|
||||
public int Do()
|
||||
{
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关联当前查询所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">要保存的架构上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前查询已绑定的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>测试期间保存的架构上下文。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
}
|
||||
58
GFramework.Core.Tests/Architectures/TestSystemV2.cs
Normal file
58
GFramework.Core.Tests/Architectures/TestSystemV2.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Enums;
|
||||
using GFramework.Core.Abstractions.Systems;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的测试系统桩。
|
||||
/// </summary>
|
||||
public sealed class TestSystemV2 : ISystem
|
||||
{
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置测试用标识。
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联当前系统所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">要保存的架构上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前系统已绑定的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>测试期间保存的架构上下文。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化测试系统。
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁测试系统。
|
||||
/// </summary>
|
||||
public void Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收架构阶段切换通知。
|
||||
/// </summary>
|
||||
/// <param name="phase">当前架构阶段。</param>
|
||||
public void OnArchitecturePhase(ArchitecturePhase phase)
|
||||
{
|
||||
}
|
||||
}
|
||||
35
GFramework.Core.Tests/Architectures/TestUtilityV2.cs
Normal file
35
GFramework.Core.Tests/Architectures/TestUtilityV2.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Utility;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ArchitectureContextTests" /> 提供的测试工具桩。
|
||||
/// </summary>
|
||||
public sealed class TestUtilityV2 : IUtility
|
||||
{
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置测试用标识。
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联当前工具所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">要保存的架构上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前工具已绑定的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>测试期间保存的架构上下文。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
using System.Threading;
|
||||
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||
|
||||
namespace GFramework.Core.Tests.Architectures;
|
||||
|
||||
/// <summary>
|
||||
/// 记录请求通过管道次数的测试行为。
|
||||
/// </summary>
|
||||
/// <typeparam name="TRequest">请求类型。</typeparam>
|
||||
/// <typeparam name="TResponse">响应类型。</typeparam>
|
||||
public sealed class TrackingPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
private static int _invocationCount;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前测试进程中该请求类型对应的行为触发次数。
|
||||
/// 该计数器是按泛型闭包共享的静态状态,测试需要在每次运行前显式重置。
|
||||
/// </summary>
|
||||
public static int InvocationCount
|
||||
{
|
||||
get => Volatile.Read(ref _invocationCount);
|
||||
set => Volatile.Write(ref _invocationCount, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以线程安全方式记录一次行为执行,然后继续执行下一个处理器。
|
||||
/// </summary>
|
||||
/// <param name="message">当前请求消息。</param>
|
||||
/// <param name="next">下一个处理委托。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>下游处理器的响应结果。</returns>
|
||||
public async ValueTask<TResponse> Handle(
|
||||
TRequest message,
|
||||
MessageHandlerDelegate<TRequest, TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Interlocked.Increment(ref _invocationCount);
|
||||
return await next(message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@ -229,171 +229,3 @@ public class AbstractAsyncCommandTests
|
||||
Assert.That(result, Is.EqualTo(200));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用命令输入类V2
|
||||
/// </summary>
|
||||
public sealed class TestCommandInputV2 : ICommandInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置值
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步命令类V3(无返回值)
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandV3 : AbstractAsyncCommand<TestCommandInputV2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommandV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行的值
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>表示异步操作的任务</returns>
|
||||
protected override Task OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = input.Value;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步命令类V3(有返回值)
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithResultV3 : AbstractAsyncCommand<TestCommandInputV2, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommandWithResultV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令并返回结果的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>执行结果的异步任务</returns>
|
||||
protected override Task<int> OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
return Task.FromResult(input.Value * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步命令类(抛出异常)
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithExceptionV3 : AbstractAsyncCommand<TestCommandInputV2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommandWithExceptionV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令并抛出异常的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>表示异步操作的任务</returns>
|
||||
/// <exception cref="InvalidOperationException">总是抛出异常</exception>
|
||||
protected override Task OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
throw new InvalidOperationException("Test exception");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步命令子类(无返回值)
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandChildV3 : AbstractAsyncCommand<TestCommandInputV2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommandChildV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行的值
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令的重写方法(子类实现)
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>表示异步操作的任务</returns>
|
||||
protected override Task OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = input.Value * 2;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步命令子类(有返回值)
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithResultChildV3 : AbstractAsyncCommand<TestCommandInputV2, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommandWithResultChildV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令并返回结果的重写方法(子类实现)
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>执行结果的异步任务</returns>
|
||||
protected override Task<int> OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
return Task.FromResult(input.Value * 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<ArgumentNullException>(() => _commandExecutor.SendAsync<int>(null!));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用命令输入类,实现ICommandInput接口
|
||||
/// </summary>
|
||||
public sealed class TestCommandInput : ICommandInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置值
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用命令类,继承AbstractCommand
|
||||
/// </summary>
|
||||
public sealed class TestCommand : AbstractCommand<TestCommandInput>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestCommand(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行的值
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行命令的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
protected override void OnExecute(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = 42;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用带返回值的命令类,继承AbstractCommand
|
||||
/// </summary>
|
||||
public sealed class TestCommandWithResult : AbstractCommand<TestCommandInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestCommandWithResult(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行命令并返回结果的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>执行结果</returns>
|
||||
protected override int OnExecute(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
return input.Value * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步命令类,继承AbstractAsyncCommand
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommand : AbstractAsyncCommand<TestCommandInput>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommand(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行的值
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>表示异步操作的任务</returns>
|
||||
protected override Task OnExecuteAsync(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = 42;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用带返回值的异步命令类,继承AbstractAsyncCommand
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithResult : AbstractAsyncCommand<TestCommandInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
public TestAsyncCommandWithResult(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令是否已执行
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步命令并返回结果的重写方法
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入</param>
|
||||
/// <returns>执行结果的异步任务</returns>
|
||||
protected override Task<int> OnExecuteAsync(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
return Task.FromResult(input.Value * 2);
|
||||
}
|
||||
}
|
||||
|
||||
39
GFramework.Core.Tests/Command/TestAsyncCommand.cs
Normal file
39
GFramework.Core.Tests/Command/TestAsyncCommand.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="CommandExecutorTests" /> 使用的异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommand : AbstractAsyncCommand<TestCommandInput>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommand" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommand(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令记录的执行结果值。
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步测试命令并记录执行状态。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>已完成的异步任务。</returns>
|
||||
protected override Task OnExecuteAsync(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = 42;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
39
GFramework.Core.Tests/Command/TestAsyncCommandChildV3.cs
Normal file
39
GFramework.Core.Tests/Command/TestAsyncCommandChildV3.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AbstractAsyncCommandTests" /> 使用的子类化无返回值异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandChildV3 : AbstractAsyncCommand<TestCommandInputV2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommandChildV3" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommandChildV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取子类记录的执行值。
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行子类测试命令并记录经过变换的输入值。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>已完成的异步任务。</returns>
|
||||
protected override Task OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = input.Value * 2;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
39
GFramework.Core.Tests/Command/TestAsyncCommandV3.cs
Normal file
39
GFramework.Core.Tests/Command/TestAsyncCommandV3.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AbstractAsyncCommandTests" /> 使用的无返回值异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandV3 : AbstractAsyncCommand<TestCommandInputV2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommandV3" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommandV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令记录的执行值。
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令并回写执行状态。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>已完成的异步任务。</returns>
|
||||
protected override Task OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = input.Value;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AbstractAsyncCommandTests" /> 使用的异常路径异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithExceptionV3 : AbstractAsyncCommand<TestCommandInputV2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommandWithExceptionV3" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommandWithExceptionV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令并始终抛出预期异常。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>此方法不会正常返回。</returns>
|
||||
/// <exception cref="InvalidOperationException">始终抛出,用于验证异常传播行为。</exception>
|
||||
protected override Task OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
throw new InvalidOperationException("Test exception");
|
||||
}
|
||||
}
|
||||
33
GFramework.Core.Tests/Command/TestAsyncCommandWithResult.cs
Normal file
33
GFramework.Core.Tests/Command/TestAsyncCommandWithResult.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="CommandExecutorTests" /> 使用的带返回值异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithResult : AbstractAsyncCommand<TestCommandInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommandWithResult" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommandWithResult(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步测试命令并返回基于输入值计算的结果。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>输入值两倍的异步结果。</returns>
|
||||
protected override Task<int> OnExecuteAsync(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
return Task.FromResult(input.Value * 2);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AbstractAsyncCommandTests" /> 使用的子类化带返回值异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithResultChildV3 : AbstractAsyncCommand<TestCommandInputV2, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommandWithResultChildV3" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommandWithResultChildV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行子类测试命令并返回经过变换的输入值。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>输入值三倍的异步结果。</returns>
|
||||
protected override Task<int> OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
return Task.FromResult(input.Value * 3);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AbstractAsyncCommandTests" /> 使用的带返回值异步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncCommandWithResultV3 : AbstractAsyncCommand<TestCommandInputV2, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncCommandWithResultV3" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestAsyncCommandWithResultV3(TestCommandInputV2 input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令并返回基于输入值计算的结果。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>输入值两倍的异步结果。</returns>
|
||||
protected override Task<int> OnExecuteAsync(TestCommandInputV2 input)
|
||||
{
|
||||
Executed = true;
|
||||
return Task.FromResult(input.Value * 2);
|
||||
}
|
||||
}
|
||||
37
GFramework.Core.Tests/Command/TestCommand.cs
Normal file
37
GFramework.Core.Tests/Command/TestCommand.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="CommandExecutorTests" /> 使用的同步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestCommand : AbstractCommand<TestCommandInput>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestCommand" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestCommand(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取命令记录的执行结果值。
|
||||
/// </summary>
|
||||
public int ExecutedValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令并记录同步执行状态。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
protected override void OnExecute(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
ExecutedValue = 42;
|
||||
}
|
||||
}
|
||||
14
GFramework.Core.Tests/Command/TestCommandInput.cs
Normal file
14
GFramework.Core.Tests/Command/TestCommandInput.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="CommandExecutorTests" /> 使用的测试命令输入。
|
||||
/// </summary>
|
||||
public sealed class TestCommandInput : ICommandInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置测试值。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
14
GFramework.Core.Tests/Command/TestCommandInputV2.cs
Normal file
14
GFramework.Core.Tests/Command/TestCommandInputV2.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AbstractAsyncCommandTests" /> 使用的测试命令输入。
|
||||
/// </summary>
|
||||
public sealed class TestCommandInputV2 : ICommandInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置用于驱动测试断言的输入值。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
33
GFramework.Core.Tests/Command/TestCommandWithResult.cs
Normal file
33
GFramework.Core.Tests/Command/TestCommandWithResult.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using GFramework.Core.Command;
|
||||
|
||||
namespace GFramework.Core.Tests.Command;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="CommandExecutorTests" /> 使用的带返回值同步测试命令。
|
||||
/// </summary>
|
||||
public sealed class TestCommandWithResult : AbstractCommand<TestCommandInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestCommandWithResult" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
public TestCommandWithResult(TestCommandInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示命令是否已经执行。
|
||||
/// </summary>
|
||||
public bool Executed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行测试命令并返回基于输入值计算的结果。
|
||||
/// </summary>
|
||||
/// <param name="input">命令输入。</param>
|
||||
/// <returns>输入值的两倍。</returns>
|
||||
protected override int OnExecute(TestCommandInput input)
|
||||
{
|
||||
Executed = true;
|
||||
return input.Value * 2;
|
||||
}
|
||||
}
|
||||
63
GFramework.Core.Tests/Coroutine/ComplexQuery.cs
Normal file
63
GFramework.Core.Tests/Coroutine/ComplexQuery.cs
Normal file
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="QueryCoroutineExtensionsTests" /> 提供复杂对象结果的查询测试替身。
|
||||
/// </summary>
|
||||
internal class ComplexQuery : IQuery<ComplexResult>
|
||||
{
|
||||
private IArchitectureContext? _context;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置测试查询使用的名称。
|
||||
/// </summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置需要聚合的整数集合。
|
||||
/// </summary>
|
||||
public List<int> Values { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置附加元数据。
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Metadata { get; set; } = new(StringComparer.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// 绑定当前查询所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">测试期间由查询管线注入的上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前查询持有的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>此前通过 <see cref="SetContext" /> 绑定的上下文实例。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context ?? throw new InvalidOperationException(
|
||||
$"{nameof(SetContext)} must be called before {nameof(GetContext)}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询并生成复杂结果对象。
|
||||
/// </summary>
|
||||
/// <returns>包含名称、求和值和计数信息的测试结果。</returns>
|
||||
public ComplexResult Do()
|
||||
{
|
||||
return new ComplexResult
|
||||
{
|
||||
ProcessedName = Name,
|
||||
Sum = Values.Sum(),
|
||||
Count = Values.Count
|
||||
};
|
||||
}
|
||||
}
|
||||
22
GFramework.Core.Tests/Coroutine/ComplexResult.cs
Normal file
22
GFramework.Core.Tests/Coroutine/ComplexResult.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace GFramework.Core.Tests.Coroutine;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ComplexQuery" /> 提供复杂对象结果的测试载体。
|
||||
/// </summary>
|
||||
internal class ComplexResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置处理后的名称。
|
||||
/// </summary>
|
||||
public string ProcessedName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置整数集合的求和结果。
|
||||
/// </summary>
|
||||
public int Sum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置整数集合中的元素数量。
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
}
|
||||
@ -610,28 +610,3 @@ public class CoroutineSchedulerTests
|
||||
throw new InvalidOperationException("Test exception");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用时间源类,实现ITimeSource接口
|
||||
/// </summary>
|
||||
public class TestTimeSource : ITimeSource
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前时间
|
||||
/// </summary>
|
||||
public double CurrentTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取时间增量
|
||||
/// </summary>
|
||||
public double DeltaTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间源状态
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
DeltaTime = 0.1;
|
||||
CurrentTime += DeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
44
GFramework.Core.Tests/Coroutine/IntQuery.cs
Normal file
44
GFramework.Core.Tests/Coroutine/IntQuery.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Abstractions.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Coroutine;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="QueryCoroutineExtensionsTests" /> 提供布尔结果的整数查询测试替身。
|
||||
/// </summary>
|
||||
internal class IntQuery : IQuery<bool>
|
||||
{
|
||||
private IArchitectureContext? _context;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置参与查询计算的整数值。
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定当前查询所属的架构上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">测试期间由查询管线注入的上下文。</param>
|
||||
public void SetContext(IArchitectureContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前查询持有的架构上下文。
|
||||
/// </summary>
|
||||
/// <returns>此前通过 <see cref="SetContext" /> 绑定的上下文实例。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询并返回布尔结果。
|
||||
/// </summary>
|
||||
/// <returns>当 <see cref="Value" /> 大于零时返回 <see langword="true" />。</returns>
|
||||
public bool Do()
|
||||
{
|
||||
return Value > 0;
|
||||
}
|
||||
}
|
||||
@ -329,63 +329,3 @@ public class QueryCoroutineExtensionsTests
|
||||
Assert.That(receivedResult, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于测试的整数查询类
|
||||
/// </summary>
|
||||
internal class IntQuery : IQuery<bool>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于测试的复杂查询类
|
||||
/// </summary>
|
||||
internal class ComplexQuery : IQuery<ComplexResult>
|
||||
{
|
||||
private IArchitectureContext? _context;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public List<int> Values { get; set; } = new();
|
||||
public Dictionary<string, object> 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 };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于测试的复杂结果类
|
||||
/// </summary>
|
||||
internal class ComplexResult
|
||||
{
|
||||
public string ProcessedName { get; set; } = string.Empty;
|
||||
public int Sum { get; set; }
|
||||
public int Count { get; set; }
|
||||
}
|
||||
|
||||
28
GFramework.Core.Tests/Coroutine/TestTimeSource.cs
Normal file
28
GFramework.Core.Tests/Coroutine/TestTimeSource.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using GFramework.Core.Abstractions.Coroutine;
|
||||
|
||||
namespace GFramework.Core.Tests.Coroutine;
|
||||
|
||||
/// <summary>
|
||||
/// 为协程测试提供固定时间步长的时间源。
|
||||
/// </summary>
|
||||
public sealed class TestTimeSource : ITimeSource
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前累计时间。
|
||||
/// </summary>
|
||||
public double CurrentTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次更新产生的时间增量。
|
||||
/// </summary>
|
||||
public double DeltaTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 按固定步长推进测试时间,确保调度器测试具有确定性。
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
DeltaTime = 0.1;
|
||||
CurrentTime += DeltaTime;
|
||||
}
|
||||
}
|
||||
21
GFramework.Core.Tests/Cqrs/DeterministicOrderNotification.cs
Normal file
21
GFramework.Core.Tests/Cqrs/DeterministicOrderNotification.cs
Normal file
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 为容器层测试提供可扫描的最小通知夹具。
|
||||
/// </summary>
|
||||
internal sealed record DeterministicOrderNotification : INotification;
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 为容器层测试提供可扫描的最小通知夹具。
|
||||
/// </summary>
|
||||
internal sealed record DeterministicOrderNotification : INotification;
|
||||
|
||||
/// <summary>
|
||||
/// 供容器注册测试验证程序集扫描结果的通知处理器。
|
||||
/// </summary>
|
||||
@ -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<string>("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<List<int>>("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<string>("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<List<int>>("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<string>("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<string>("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<string>("testKey");
|
||||
|
||||
@ -184,31 +184,3 @@ public class EnvironmentTests
|
||||
Assert.That(result, Is.EqualTo("interfaceValue"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试环境实现类,继承自EnvironmentBase
|
||||
/// </summary>
|
||||
public class TestEnvironment : EnvironmentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取环境名称
|
||||
/// </summary>
|
||||
public override string Name { get; } = "TestEnvironment";
|
||||
|
||||
/// <summary>
|
||||
/// 注册键值对到环境中
|
||||
/// </summary>
|
||||
/// <param name="key">要注册的键</param>
|
||||
/// <param name="value">要注册的值</param>
|
||||
public new void Register(string key, object value)
|
||||
{
|
||||
base.Register(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化环境
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
GFramework.Core.Tests/Environment/TestEnvironment.cs
Normal file
34
GFramework.Core.Tests/Environment/TestEnvironment.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using GFramework.Core.Environment;
|
||||
|
||||
namespace GFramework.Core.Tests.Environment;
|
||||
|
||||
/// <summary>
|
||||
/// 为环境相关测试提供可写注册入口的测试环境实现。
|
||||
/// </summary>
|
||||
public sealed class TestEnvironment : EnvironmentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取测试环境名称。
|
||||
/// </summary>
|
||||
public override string Name { get; } = "TestEnvironment";
|
||||
|
||||
/// <summary>
|
||||
/// 将测试数据注册到基础环境存储中,便于测试通过显式测试辅助入口准备上下文。
|
||||
/// </summary>
|
||||
/// <param name="key">要注册的环境键。</param>
|
||||
/// <param name="value">要注册的环境值。</param>
|
||||
public void RegisterForTest(string key, object value)
|
||||
{
|
||||
base.Register(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化测试环境。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当前测试环境没有额外初始化逻辑,但仍保留重写以匹配 <see cref="EnvironmentBase"/> 契约。
|
||||
/// </remarks>
|
||||
public override void Initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -76,10 +76,3 @@ public class EventBusTests
|
||||
Assert.That(count2, Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EventBus测试专用事件类
|
||||
/// </summary>
|
||||
public class EventBusTestsEvent
|
||||
{
|
||||
}
|
||||
8
GFramework.Core.Tests/Events/EventBusTestsEvent.cs
Normal file
8
GFramework.Core.Tests/Events/EventBusTestsEvent.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace GFramework.Core.Tests.Events;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="EventBusTests" /> 使用的测试事件。
|
||||
/// </summary>
|
||||
public class EventBusTestsEvent
|
||||
{
|
||||
}
|
||||
@ -218,19 +218,3 @@ public class ObjectExtensionsTests
|
||||
Assert.That(executed, Is.False);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用的简单类
|
||||
/// </summary>
|
||||
public class TestClass
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置整数值
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置名称字符串
|
||||
/// </summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
17
GFramework.Core.Tests/Extensions/TestClass.cs
Normal file
17
GFramework.Core.Tests/Extensions/TestClass.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace GFramework.Core.Tests.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="ObjectExtensionsTests" /> 提供类型匹配断言所需的简单测试对象。
|
||||
/// </summary>
|
||||
public class TestClass
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置用于数值分支断言的测试值。
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置用于字符串结果断言的测试名称。
|
||||
/// </summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
15
GFramework.Core.Tests/Extensions/TestUnRegisterList.cs
Normal file
15
GFramework.Core.Tests/Extensions/TestUnRegisterList.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using GFramework.Core.Abstractions.Events;
|
||||
|
||||
namespace GFramework.Core.Tests.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="UnRegisterListExtensionTests" /> 提供可观察的 <see cref="IUnRegisterList" /> 测试替身。
|
||||
/// </summary>
|
||||
public class TestUnRegisterList : IUnRegisterList
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前测试收集到的注销项列表,供断言扩展方法是否正确追加和清空元素。
|
||||
/// </summary>
|
||||
public IList<IUnRegister> UnregisterList { get; } = new List<IUnRegister>();
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用的UnRegisterList实现类,用于验证扩展方法功能
|
||||
/// </summary>
|
||||
public class TestUnRegisterList : IUnRegisterList
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置注销列表
|
||||
/// </summary>
|
||||
public IList<IUnRegister> UnregisterList { get; } = new List<IUnRegister>();
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用对象池实现类,继承自AbstractObjectPoolSystem
|
||||
/// </summary>
|
||||
public class TestObjectPool : AbstractObjectPoolSystem<string, TestPoolableObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建新的池化对象
|
||||
/// </summary>
|
||||
/// <param name="key">用于标识对象的键</param>
|
||||
/// <returns>新创建的TestPoolableObject实例</returns>
|
||||
protected override TestPoolableObject Create(string key)
|
||||
{
|
||||
return new TestPoolableObject { PoolKey = key };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化方法,用于对象池初始化时的操作
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用池化对象类,实现了IPoolableObject接口
|
||||
/// </summary>
|
||||
public class TestPoolableObject : IPoolableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置对象的池键
|
||||
/// </summary>
|
||||
public string PoolKey { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置测试用的整数值
|
||||
/// </summary>
|
||||
public int TestValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置OnAcquire方法是否被调用的标志
|
||||
/// </summary>
|
||||
public bool OnAcquireCalled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置OnRelease方法是否被调用的标志
|
||||
/// </summary>
|
||||
public bool OnReleaseCalled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置OnPoolDestroy方法是否被调用的标志
|
||||
/// </summary>
|
||||
public bool OnPoolDestroyCalled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对象被获取时的回调方法
|
||||
/// </summary>
|
||||
public void OnAcquire()
|
||||
{
|
||||
OnAcquireCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象被释放时的回调方法
|
||||
/// </summary>
|
||||
public void OnRelease()
|
||||
{
|
||||
OnReleaseCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象被销毁时的回调方法
|
||||
/// </summary>
|
||||
public void OnPoolDestroy()
|
||||
{
|
||||
OnPoolDestroyCalled = true;
|
||||
}
|
||||
}
|
||||
27
GFramework.Core.Tests/Pool/TestObjectPool.cs
Normal file
27
GFramework.Core.Tests/Pool/TestObjectPool.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using GFramework.Core.Pool;
|
||||
|
||||
namespace GFramework.Core.Tests.Pool;
|
||||
|
||||
/// <summary>
|
||||
/// 测试用对象池实现类,继承自 <see cref="AbstractObjectPoolSystem{TKey,TValue}" />,
|
||||
/// 用于验证对象池的获取、释放和统计行为。
|
||||
/// </summary>
|
||||
public class TestObjectPool : AbstractObjectPoolSystem<string, TestPoolableObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据池键创建新的测试对象。
|
||||
/// </summary>
|
||||
/// <param name="key">用于标识对象所属池的键。</param>
|
||||
/// <returns>带有对应 <paramref name="key" /> 的测试对象实例。</returns>
|
||||
protected override TestPoolableObject Create(string key)
|
||||
{
|
||||
return new TestPoolableObject { PoolKey = key };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行对象池初始化。
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
}
|
||||
}
|
||||
58
GFramework.Core.Tests/Pool/TestPoolableObject.cs
Normal file
58
GFramework.Core.Tests/Pool/TestPoolableObject.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using GFramework.Core.Abstractions.Pool;
|
||||
|
||||
namespace GFramework.Core.Tests.Pool;
|
||||
|
||||
/// <summary>
|
||||
/// 供对象池测试使用的池化对象,记录生命周期回调是否被触发。
|
||||
/// </summary>
|
||||
public class TestPoolableObject : IPoolableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置对象所属的池键。
|
||||
/// </summary>
|
||||
public string PoolKey { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置测试中写入的整数值。
|
||||
/// </summary>
|
||||
public int TestValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象获取回调是否已执行。
|
||||
/// </summary>
|
||||
public bool OnAcquireCalled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象释放回调是否已执行。
|
||||
/// </summary>
|
||||
public bool OnReleaseCalled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置对象销毁回调是否已执行。
|
||||
/// </summary>
|
||||
public bool OnPoolDestroyCalled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 在对象被对象池取出时记录回调执行状态。
|
||||
/// </summary>
|
||||
public void OnAcquire()
|
||||
{
|
||||
OnAcquireCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在对象被归还到对象池时记录回调执行状态。
|
||||
/// </summary>
|
||||
public void OnRelease()
|
||||
{
|
||||
OnReleaseCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在对象因容量限制或清池而销毁时记录回调执行状态。
|
||||
/// </summary>
|
||||
public void OnPoolDestroy()
|
||||
{
|
||||
OnPoolDestroyCalled = true;
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -137,159 +136,3 @@ public class AsyncQueryExecutorTests
|
||||
Assert.That(result2, Is.EqualTo(40));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步查询输入类,实现IQueryInput接口
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQueryInput : IQueryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置查询值
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整数类型测试异步查询类,继承AbstractAsyncQuery
|
||||
/// 实现具体的异步查询逻辑并返回整数结果
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQuery : AbstractAsyncQuery<TestAsyncQueryInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestAsyncQuery的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestAsyncQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询操作的具体实现
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <returns>查询结果,将输入值乘以2</returns>
|
||||
protected override Task<int> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
return Task.FromResult(input.Value * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字符串类型测试异步查询类,继承AbstractAsyncQuery
|
||||
/// 实现具体的异步查询逻辑并返回字符串结果
|
||||
/// </summary>
|
||||
public sealed class TestAsyncStringQuery : AbstractAsyncQuery<TestAsyncQueryInput, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestAsyncStringQuery的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestAsyncStringQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询操作的具体实现
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <returns>格式化的字符串结果</returns>
|
||||
protected override Task<string> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
return Task.FromResult($"Result: {input.Value * 2}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 布尔类型测试异步查询类,继承AbstractAsyncQuery
|
||||
/// 实现具体的异步查询逻辑并返回布尔结果
|
||||
/// </summary>
|
||||
public sealed class TestAsyncBooleanQuery : AbstractAsyncQuery<TestAsyncQueryInput, bool>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestAsyncBooleanQuery的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestAsyncBooleanQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询操作的具体实现
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <returns>如果值大于0返回true,否则返回false</returns>
|
||||
protected override Task<bool> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
return Task.FromResult(input.Value > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复杂对象类型测试异步查询类,继承AbstractAsyncQuery
|
||||
/// 实现具体的异步查询逻辑并返回复杂对象结果
|
||||
/// </summary>
|
||||
public sealed class TestAsyncComplexQuery : AbstractAsyncQuery<TestAsyncQueryInput, TestAsyncQueryResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestAsyncComplexQuery的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestAsyncComplexQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询操作的具体实现
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <returns>复杂对象查询结果</returns>
|
||||
protected override Task<TestAsyncQueryResult> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
var result = new TestAsyncQueryResult
|
||||
{
|
||||
Value = input.Value * 2,
|
||||
DoubleValue = input.Value * 3
|
||||
};
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用异步查询类(抛出异常)
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQueryWithException : AbstractAsyncQuery<TestAsyncQueryInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestAsyncQueryWithException的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestAsyncQueryWithException(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询操作并抛出异常
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <exception cref="InvalidOperationException">总是抛出异常</exception>
|
||||
protected override Task<int> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
throw new InvalidOperationException("Test exception");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用复杂查询结果类
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQueryResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置值
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置双倍值
|
||||
/// </summary>
|
||||
public int DoubleValue { get; init; }
|
||||
}
|
||||
|
||||
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用查询输入类,实现IQueryInput接口
|
||||
/// 用于传递查询所需的参数信息
|
||||
/// </summary>
|
||||
public sealed class TestQueryInput : IQueryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置查询值
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整数类型测试查询类,继承自AbstractQuery
|
||||
/// 实现具体的查询逻辑并返回整数结果
|
||||
/// </summary>
|
||||
public sealed class TestQuery : AbstractQuery<TestQueryInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestQuery的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestQuery(TestQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询操作的具体实现
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <returns>查询结果,将输入值乘以2</returns>
|
||||
protected override int OnDo(TestQueryInput input)
|
||||
{
|
||||
return input.Value * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字符串类型测试查询类,继承自AbstractQuery
|
||||
/// 实现具体的查询逻辑并返回字符串结果
|
||||
/// </summary>
|
||||
public sealed class TestStringQuery : AbstractQuery<TestQueryInput, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化TestStringQuery的新实例
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
public TestStringQuery(TestQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询操作的具体实现
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数</param>
|
||||
/// <returns>格式化的字符串结果</returns>
|
||||
protected override string OnDo(TestQueryInput input)
|
||||
{
|
||||
return $"Result: {input.Value * 2}";
|
||||
}
|
||||
}
|
||||
|
||||
27
GFramework.Core.Tests/Query/TestAsyncBooleanQuery.cs
Normal file
27
GFramework.Core.Tests/Query/TestAsyncBooleanQuery.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AsyncQueryExecutorTests" /> 提供布尔结果的测试异步查询。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncBooleanQuery : AbstractAsyncQuery<TestAsyncQueryInput, bool>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncBooleanQuery" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestAsyncBooleanQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询并根据输入值是否大于零返回布尔结果。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>当输入值大于 0 时返回 <see langword="true" />;否则返回 <see langword="false" />。</returns>
|
||||
protected override Task<bool> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
return Task.FromResult(input.Value > 0);
|
||||
}
|
||||
}
|
||||
33
GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs
Normal file
33
GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AsyncQueryExecutorTests" /> 提供复杂对象结果的测试异步查询。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncComplexQuery : AbstractAsyncQuery<TestAsyncQueryInput, TestAsyncQueryResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncComplexQuery" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestAsyncComplexQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询并构造组合结果对象。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>包含双倍值和三倍值的测试结果对象。</returns>
|
||||
protected override Task<TestAsyncQueryResult> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
var result = new TestAsyncQueryResult
|
||||
{
|
||||
Value = input.Value * 2,
|
||||
TripleValue = input.Value * 3
|
||||
};
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
}
|
||||
@ -31,7 +31,7 @@ public sealed class TestAsyncComplexQueryV4 : AbstractAsyncQuery<TestAsyncQueryI
|
||||
var result = new TestAsyncQueryResultV2
|
||||
{
|
||||
Value = input.Value * 2,
|
||||
DoubleValue = input.Value * 3
|
||||
TripleValue = input.Value * 3
|
||||
};
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
27
GFramework.Core.Tests/Query/TestAsyncQuery.cs
Normal file
27
GFramework.Core.Tests/Query/TestAsyncQuery.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AsyncQueryExecutorTests" /> 提供整数结果的测试异步查询。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQuery : AbstractAsyncQuery<TestAsyncQueryInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncQuery" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestAsyncQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询并返回输入值的两倍。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>将输入值乘以 2 的结果。</returns>
|
||||
protected override Task<int> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
return Task.FromResult(input.Value * 2);
|
||||
}
|
||||
}
|
||||
14
GFramework.Core.Tests/Query/TestAsyncQueryInput.cs
Normal file
14
GFramework.Core.Tests/Query/TestAsyncQueryInput.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AsyncQueryExecutorTests" /> 提供输入值的测试查询输入。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQueryInput : IQueryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取查询值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
17
GFramework.Core.Tests/Query/TestAsyncQueryResult.cs
Normal file
17
GFramework.Core.Tests/Query/TestAsyncQueryResult.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 表示 <see cref="AsyncQueryExecutorTests" /> 使用的复杂测试查询结果。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQueryResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取主结果值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取派生的三倍结果值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int TripleValue { get; init; }
|
||||
}
|
||||
@ -6,12 +6,12 @@ namespace GFramework.Core.Tests.Query;
|
||||
public sealed class TestAsyncQueryResultV2
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置值
|
||||
/// 获取值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置双倍值
|
||||
/// 获取三倍值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int DoubleValue { get; init; }
|
||||
public int TripleValue { get; init; }
|
||||
}
|
||||
|
||||
28
GFramework.Core.Tests/Query/TestAsyncQueryWithException.cs
Normal file
28
GFramework.Core.Tests/Query/TestAsyncQueryWithException.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AsyncQueryExecutorTests" /> 提供固定抛出异常的测试异步查询。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncQueryWithException : AbstractAsyncQuery<TestAsyncQueryInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncQueryWithException" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestAsyncQueryWithException(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询并始终抛出测试异常。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>此方法不会返回结果。</returns>
|
||||
/// <exception cref="InvalidOperationException">始终抛出,模拟查询执行失败。</exception>
|
||||
protected override Task<int> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
throw new InvalidOperationException("Test exception");
|
||||
}
|
||||
}
|
||||
27
GFramework.Core.Tests/Query/TestAsyncStringQuery.cs
Normal file
27
GFramework.Core.Tests/Query/TestAsyncStringQuery.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AsyncQueryExecutorTests" /> 提供字符串结果的测试异步查询。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncStringQuery : AbstractAsyncQuery<TestAsyncQueryInput, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestAsyncStringQuery" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestAsyncStringQuery(TestAsyncQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步查询并返回格式化的字符串结果。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>包含双倍值的格式化字符串。</returns>
|
||||
protected override Task<string> OnDoAsync(TestAsyncQueryInput input)
|
||||
{
|
||||
return Task.FromResult($"Result: {input.Value * 2}");
|
||||
}
|
||||
}
|
||||
27
GFramework.Core.Tests/Query/TestQuery.cs
Normal file
27
GFramework.Core.Tests/Query/TestQuery.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="QueryExecutorTests" /> 提供整数结果的测试同步查询。
|
||||
/// </summary>
|
||||
public sealed class TestQuery : AbstractQuery<TestQueryInput, int>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestQuery" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestQuery(TestQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行同步查询并返回输入值的双倍结果。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>输入值乘以 2 后的结果。</returns>
|
||||
protected override int OnDo(TestQueryInput input)
|
||||
{
|
||||
return input.Value * 2;
|
||||
}
|
||||
}
|
||||
14
GFramework.Core.Tests/Query/TestQueryInput.cs
Normal file
14
GFramework.Core.Tests/Query/TestQueryInput.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using GFramework.Cqrs.Abstractions.Cqrs.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="QueryExecutorTests" /> 提供输入值的测试查询输入。
|
||||
/// </summary>
|
||||
public sealed class TestQueryInput : IQueryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置查询值。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
27
GFramework.Core.Tests/Query/TestStringQuery.cs
Normal file
27
GFramework.Core.Tests/Query/TestStringQuery.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using GFramework.Core.Query;
|
||||
|
||||
namespace GFramework.Core.Tests.Query;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="QueryExecutorTests" /> 提供字符串结果的测试同步查询。
|
||||
/// </summary>
|
||||
public sealed class TestStringQuery : AbstractQuery<TestQueryInput, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="TestStringQuery" /> 的新实例。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
public TestStringQuery(TestQueryInput input) : base(input)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行同步查询并返回格式化后的字符串结果。
|
||||
/// </summary>
|
||||
/// <param name="input">查询输入参数。</param>
|
||||
/// <returns>包含双倍值的格式化字符串。</returns>
|
||||
protected override string OnDo(TestQueryInput input)
|
||||
{
|
||||
return $"Result: {input.Value * 2}";
|
||||
}
|
||||
}
|
||||
@ -99,29 +99,3 @@ public class ContextAwareTests
|
||||
Assert.DoesNotThrow(() => aware.GetContext());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于测试的 ContextAware 实现类
|
||||
/// 继承自 ContextAwareBase,提供公共访问的上下文属性和回调状态跟踪
|
||||
/// </summary>
|
||||
public class TestContextAware : ContextAwareBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取内部上下文的公共访问属性
|
||||
/// </summary>
|
||||
public IArchitectureContext? PublicContext => Context;
|
||||
|
||||
/// <summary>
|
||||
/// 跟踪 OnContextReady 方法是否被调用的状态
|
||||
/// </summary>
|
||||
public bool OnContextReadyCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重写上下文就绪回调方法
|
||||
/// 设置 OnContextReadyCalled 标志为 true,用于测试验证
|
||||
/// </summary>
|
||||
protected override void OnContextReady()
|
||||
{
|
||||
OnContextReadyCalled = true;
|
||||
}
|
||||
}
|
||||
28
GFramework.Core.Tests/Rule/TestContextAware.cs
Normal file
28
GFramework.Core.Tests/Rule/TestContextAware.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using GFramework.Core.Abstractions.Architectures;
|
||||
using GFramework.Core.Rule;
|
||||
|
||||
namespace GFramework.Core.Tests.Rule;
|
||||
|
||||
/// <summary>
|
||||
/// 提供给 ContextAware 相关测试复用的上下文感知对象。
|
||||
/// </summary>
|
||||
public class TestContextAware : ContextAwareBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前测试对象已绑定的上下文实例。
|
||||
/// </summary>
|
||||
public IArchitectureContext? PublicContext => Context;
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,指示上下文就绪回调是否已经触发。
|
||||
/// </summary>
|
||||
public bool OnContextReadyCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 在上下文完成绑定后记录回调已被触发,供断言使用。
|
||||
/// </summary>
|
||||
protected override void OnContextReady()
|
||||
{
|
||||
OnContextReadyCalled = true;
|
||||
}
|
||||
}
|
||||
116
GFramework.Core.Tests/State/ConcreteAsyncStateV2.cs
Normal file
116
GFramework.Core.Tests/State/ConcreteAsyncStateV2.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 异步具体状态实现类V2版本,用于测试异步状态的基本功能。
|
||||
/// </summary>
|
||||
public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许转换。
|
||||
/// </summary>
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态被调用的次数。
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态被调用的次数。
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置转换到目标状态时执行的动作。
|
||||
/// </summary>
|
||||
public Action<IState>? CanTransitionToAsyncAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步进入当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
public async Task OnEnterAsync(IState? from)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步退出当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
public async Task OnExitAsync(IState? to)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步判断是否可以转换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>如果可以转换则返回 <see langword="true" />,否则返回 <see langword="false" />。</returns>
|
||||
public async Task<bool> CanTransitionToAsync(IState target)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
CanTransitionToAsyncAction?.Invoke(target);
|
||||
return AllowTransitions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法(同步版本,抛出异常表示不应被调用)。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
/// <exception cref="InvalidOperationException">总是抛出,表示异步状态不应走同步入口。</exception>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnEnter should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法(同步版本,抛出异常表示不应被调用)。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
/// <exception cref="InvalidOperationException">总是抛出,表示异步状态不应走同步入口。</exception>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnExit should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用)。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>此方法不会正常返回。</returns>
|
||||
/// <exception cref="InvalidOperationException">总是抛出,表示异步状态不应走同步入口。</exception>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
|
||||
}
|
||||
}
|
||||
70
GFramework.Core.Tests/State/ConcreteStateV2.cs
Normal file
70
GFramework.Core.Tests/State/ConcreteStateV2.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 具体状态实现类V2版本,用于测试状态的基本功能。
|
||||
/// </summary>
|
||||
public sealed class ConcreteStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许转换。
|
||||
/// </summary>
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置转换到目标状态时执行的动作。
|
||||
/// </summary>
|
||||
public Action<IState>? CanTransitionToAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>如果可以转换则返回 <see langword="true" />,否则返回 <see langword="false" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
CanTransitionToAction?.Invoke(target);
|
||||
return AllowTransitions;
|
||||
}
|
||||
}
|
||||
59
GFramework.Core.Tests/State/ConcreteStateV3.cs
Normal file
59
GFramework.Core.Tests/State/ConcreteStateV3.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 具体状态实现类V3版本,用于测试状态的基本功能。
|
||||
/// </summary>
|
||||
public sealed class ConcreteStateV3 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
59
GFramework.Core.Tests/State/ConcreteStateV4.cs
Normal file
59
GFramework.Core.Tests/State/ConcreteStateV4.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 具体状态实现类V4版本,用于测试状态的基本功能。
|
||||
/// </summary>
|
||||
public sealed class ConcreteStateV4 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
64
GFramework.Core.Tests/State/ConditionalStateV2.cs
Normal file
64
GFramework.Core.Tests/State/ConditionalStateV2.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 条件状态实现类V2版本,支持基于类型的条件转换规则。
|
||||
/// </summary>
|
||||
public sealed class ConditionalStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置允许转换到的状态类型数组。
|
||||
/// </summary>
|
||||
public Type[] AllowedTransitions { get; set; } = Array.Empty<Type>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>如果目标状态类型在允许列表中则返回 <see langword="true" />,否则返回 <see langword="false" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return AllowedTransitions.Contains(target.GetType());
|
||||
}
|
||||
}
|
||||
24
GFramework.Core.Tests/State/StateMachineExtensions.cs
Normal file
24
GFramework.Core.Tests/State/StateMachineExtensions.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System.Reflection;
|
||||
using GFramework.Core.Abstractions.State;
|
||||
using GFramework.Core.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为状态机测试提供仅限断言场景使用的反射辅助方法。
|
||||
/// </summary>
|
||||
public static class StateMachineExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查状态机内部缓存中是否已注册指定类型的状态。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要检查的状态类型。</typeparam>
|
||||
/// <param name="stateMachine">待检查的状态机实例。</param>
|
||||
/// <returns>找到对应状态类型时返回 <see langword="true" />,否则返回 <see langword="false" />。</returns>
|
||||
public static bool ContainsState<T>(this StateMachine stateMachine) where T : IState
|
||||
{
|
||||
return stateMachine.GetType().GetField("States", BindingFlags.NonPublic | BindingFlags.Instance)?
|
||||
.GetValue(stateMachine) is Dictionary<Type, IState> states &&
|
||||
states.ContainsKey(typeof(T));
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// 测试用的ContextAwareStateMachine派生类,用于访问内部状态字典
|
||||
/// </summary>
|
||||
public class TestStateMachineSystemV5 : StateMachineSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取状态机内部的状态字典
|
||||
/// </summary>
|
||||
/// <returns>类型到状态实例的映射字典</returns>
|
||||
public IDictionary<Type, IState> GetStates()
|
||||
{
|
||||
return States;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用的上下文感知状态基类实现
|
||||
/// </summary>
|
||||
public class TestContextAwareStateV5 : ContextAwareStateBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 进入状态时调用
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态</param>
|
||||
public override void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态</param>
|
||||
public override void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 第二个测试用的上下文感知状态基类实现
|
||||
/// </summary>
|
||||
public class TestContextAwareStateV5_2 : ContextAwareStateBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 进入状态时调用
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态</param>
|
||||
public override void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态</param>
|
||||
public override void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用的普通状态实现
|
||||
/// </summary>
|
||||
public class TestStateV5 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态标识符
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以转换到指定状态
|
||||
/// </summary>
|
||||
/// <param name="next">目标状态</param>
|
||||
/// <returns>始终返回true表示允许转换</returns>
|
||||
public bool CanTransitionTo(IState next)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时调用
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态</param>
|
||||
public void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态</param>
|
||||
public void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 第二个测试用的普通状态实现,用于区分不同状态类型
|
||||
/// </summary>
|
||||
public class TestStateV5_2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态标识符
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以转换到指定状态
|
||||
/// </summary>
|
||||
/// <param name="next">目标状态</param>
|
||||
/// <returns>始终返回true表示允许转换</returns>
|
||||
public bool CanTransitionTo(IState next)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时调用
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态</param>
|
||||
public void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态</param>
|
||||
public void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试状态类V2版本,实现IState接口用于测试
|
||||
/// </summary>
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return AllowTransition;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试状态类V3版本,实现IState接口用于测试
|
||||
/// </summary>
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试状态类V4版本,实现IState接口用于测试
|
||||
/// </summary>
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步测试状态类,同时实现IState和IAsyncState接口用于测试异步状态功能
|
||||
/// </summary>
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步进入状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public async Task OnEnterAsync(IState? from)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步离开状态时的回调方法
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public async Task OnExitAsync(IState? to)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public async Task<bool> CanTransitionToAsync(IState target)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
CanTransitionToCallCount++;
|
||||
return AllowTransition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时的回调方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnEnter should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开状态时的回调方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="to">离开到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnExit should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>是否允许转换</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态机扩展方法类
|
||||
/// </summary>
|
||||
public static class StateMachineExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查状态机是否包含指定类型的状态
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要检查的状态类型</typeparam>
|
||||
/// <param name="stateMachine">状态机实例</param>
|
||||
/// <returns>如果包含指定类型的状态则返回true,否则返回false</returns>
|
||||
public static bool ContainsState<T>(this StateMachine stateMachine) where T : IState
|
||||
{
|
||||
return stateMachine.GetType().GetField("States", BindingFlags.NonPublic | BindingFlags.Instance)?
|
||||
.GetValue(stateMachine) is Dictionary<Type, IState> states &&
|
||||
states.ContainsKey(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,409 +326,3 @@ public class StateTests
|
||||
Assert.That(state.ExitCallCount, Is.EqualTo(2));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 具体状态实现类V2版本,用于测试状态的基本功能
|
||||
/// </summary>
|
||||
public sealed class ConcreteStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许转换
|
||||
/// </summary>
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置转换到目标状态时执行的动作
|
||||
/// </summary>
|
||||
public Action<IState>? CanTransitionToAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
CanTransitionToAction?.Invoke(target);
|
||||
return AllowTransitions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 具体状态实现类V3版本,用于测试状态的基本功能
|
||||
/// </summary>
|
||||
public sealed class ConcreteStateV3 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 具体状态实现类V4版本,用于测试状态的基本功能
|
||||
/// </summary>
|
||||
public sealed class ConcreteStateV4 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 条件状态实现类V2版本,支持基于类型的条件转换规则
|
||||
/// </summary>
|
||||
public sealed class ConditionalStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置允许转换到的状态类型数组
|
||||
/// </summary>
|
||||
public Type[] AllowedTransitions { get; set; } = Array.Empty<Type>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果目标状态类型在允许列表中则返回true,否则返回false</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return AllowedTransitions.Contains(target.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跟踪状态实现类V2版本,用于跟踪状态转换次数
|
||||
/// </summary>
|
||||
public sealed class TrackingStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态被调用的次数
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态被调用的次数
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>总是返回true</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步具体状态实现类V2版本,用于测试异步状态的基本功能
|
||||
/// </summary>
|
||||
public sealed class ConcreteAsyncStateV2 : IState, IAsyncState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许转换
|
||||
/// </summary>
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态是否被调用的标志
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态被调用的次数
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态被调用的次数
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置转换到目标状态时执行的动作
|
||||
/// </summary>
|
||||
public Action<IState>? CanTransitionToAsyncAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步进入当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public async Task OnEnterAsync(IState? from)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步退出当前状态时调用的方法
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public async Task OnExitAsync(IState? to)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步判断是否可以转换到目标状态
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public async Task<bool> CanTransitionToAsync(IState target)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
CanTransitionToAsyncAction?.Invoke(target);
|
||||
return AllowTransitions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnEnter should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnExit should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态(同步版本,抛出异常表示不应被调用)
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态</param>
|
||||
/// <returns>如果可以转换则返回true,否则返回false</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
|
||||
}
|
||||
}
|
||||
|
||||
116
GFramework.Core.Tests/State/TestAsyncState.cs
Normal file
116
GFramework.Core.Tests/State/TestAsyncState.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineTests" /> 提供异步生命周期路径的测试状态。
|
||||
/// </summary>
|
||||
public sealed class TestAsyncState : IState, IAsyncState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许向目标状态转移。
|
||||
/// </summary>
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步进入状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步离开状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步进入回调被调用的次数。
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步离开回调被调用的次数。
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次异步进入时的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次异步离开时的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步转移检查被调用的次数。
|
||||
/// </summary>
|
||||
public int CanTransitionToCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 异步记录进入状态的来源状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="from">触发进入的来源状态。</param>
|
||||
public async Task OnEnterAsync(IState? from)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步记录离开状态的目标状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="to">即将切换到的目标状态。</param>
|
||||
public async Task OnExitAsync(IState? to)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步记录转移检查并返回当前是否允许切换。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>允许切换时返回 <see langword="true" />,否则返回 <see langword="false" />。</returns>
|
||||
public async Task<bool> CanTransitionToAsync(IState target)
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
CanTransitionToCallCount++;
|
||||
return AllowTransitions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步进入入口不应被异步状态机路径调用。
|
||||
/// </summary>
|
||||
/// <param name="from">触发进入的来源状态。</param>
|
||||
/// <exception cref="InvalidOperationException">总是抛出,表示当前测试状态只允许异步入口。</exception>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnEnter should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步离开入口不应被异步状态机路径调用。
|
||||
/// </summary>
|
||||
/// <param name="to">即将切换到的目标状态。</param>
|
||||
/// <exception cref="InvalidOperationException">总是抛出,表示当前测试状态只允许异步入口。</exception>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
throw new InvalidOperationException("Sync OnExit should not be called for async state");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步转移检查入口不应被异步状态机路径调用。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>此方法不会正常返回。</returns>
|
||||
/// <exception cref="InvalidOperationException">总是抛出,表示当前测试状态只允许异步入口。</exception>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
throw new InvalidOperationException("Sync CanTransitionTo should not be called for async state");
|
||||
}
|
||||
}
|
||||
26
GFramework.Core.Tests/State/TestContextAwareStateV5.cs
Normal file
26
GFramework.Core.Tests/State/TestContextAwareStateV5.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
using GFramework.Core.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineSystemTests" /> 提供最小化的上下文感知状态实现。
|
||||
/// </summary>
|
||||
public class TestContextAwareStateV5 : ContextAwareStateBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 进入状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态。</param>
|
||||
public override void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态。</param>
|
||||
public override void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
26
GFramework.Core.Tests/State/TestContextAwareStateV5_2.cs
Normal file
26
GFramework.Core.Tests/State/TestContextAwareStateV5_2.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
using GFramework.Core.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineSystemTests" /> 提供第二个可区分类型的上下文感知状态实现。
|
||||
/// </summary>
|
||||
public class TestContextAwareStateV5_2 : ContextAwareStateBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 进入状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态。</param>
|
||||
public override void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态。</param>
|
||||
public override void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
22
GFramework.Core.Tests/State/TestStateMachineSystemV5.cs
Normal file
22
GFramework.Core.Tests/State/TestStateMachineSystemV5.cs
Normal file
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineSystemTests" /> 提供可观察内部状态注册表的测试状态机实现。
|
||||
/// </summary>
|
||||
public class TestStateMachineSystemV5 : StateMachineSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取状态机当前维护的状态实例映射,供测试断言注册结果使用。
|
||||
/// </summary>
|
||||
/// <returns>状态类型到状态实例的只读视图。</returns>
|
||||
public IReadOnlyDictionary<Type, IState> GetStates()
|
||||
{
|
||||
return States as IReadOnlyDictionary<Type, IState> ?? new ReadOnlyDictionary<Type, IState>(States);
|
||||
}
|
||||
}
|
||||
76
GFramework.Core.Tests/State/TestStateV2.cs
Normal file
76
GFramework.Core.Tests/State/TestStateV2.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineTests" /> 提供可配置转移结果的同步测试状态。
|
||||
/// </summary>
|
||||
public sealed class TestStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许向目标状态转移。
|
||||
/// </summary>
|
||||
public bool AllowTransition { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取离开状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入回调被调用的次数。
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取离开回调被调用的次数。
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次进入时的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次离开时的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 记录进入状态时的来源状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="from">触发进入的来源状态。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录离开状态时的目标状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="to">即将切换到的目标状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据 <see cref="AllowTransition" /> 返回是否允许切换。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>允许切换时返回 <see langword="true" />,否则返回 <see langword="false" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return AllowTransition;
|
||||
}
|
||||
}
|
||||
71
GFramework.Core.Tests/State/TestStateV3.cs
Normal file
71
GFramework.Core.Tests/State/TestStateV3.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineTests" /> 提供始终允许切换的同步测试状态。
|
||||
/// </summary>
|
||||
public sealed class TestStateV3 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取离开状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入回调被调用的次数。
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取离开回调被调用的次数。
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次进入时的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次离开时的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 记录进入状态时的来源状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="from">触发进入的来源状态。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录离开状态时的目标状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="to">即将切换到的目标状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 始终允许切换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
71
GFramework.Core.Tests/State/TestStateV4.cs
Normal file
71
GFramework.Core.Tests/State/TestStateV4.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineTests" /> 保留的附加同步测试状态实现。
|
||||
/// </summary>
|
||||
public sealed class TestStateV4 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool EnterCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取离开状态是否已被调用。
|
||||
/// </summary>
|
||||
public bool ExitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入回调被调用的次数。
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取离开回调被调用的次数。
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次进入时的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近一次离开时的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 记录进入状态时的来源状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="from">触发进入的来源状态。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCalled = true;
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录离开状态时的目标状态与调用次数。
|
||||
/// </summary>
|
||||
/// <param name="to">即将切换到的目标状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCalled = true;
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 始终允许切换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
40
GFramework.Core.Tests/State/TestStateV5.cs
Normal file
40
GFramework.Core.Tests/State/TestStateV5.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineSystemTests" /> 提供最小化的普通状态实现。
|
||||
/// </summary>
|
||||
public class TestStateV5 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置测试状态标识符。
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否允许转换到下一个状态。
|
||||
/// </summary>
|
||||
/// <param name="next">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" /> 以简化状态机切换测试。</returns>
|
||||
public bool CanTransitionTo(IState next)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态。</param>
|
||||
public void OnEnter(IState? previous)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态。</param>
|
||||
public void OnExit(IState? next)
|
||||
{
|
||||
}
|
||||
}
|
||||
43
GFramework.Core.Tests/State/TestStateV5_2.cs
Normal file
43
GFramework.Core.Tests/State/TestStateV5_2.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="StateMachineSystemTests" /> 提供第二个可区分类型的普通状态实现。
|
||||
/// </summary>
|
||||
public class TestStateV5_2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置测试状态标识符。
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否允许转换到下一个状态。
|
||||
/// </summary>
|
||||
/// <param name="next">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" /> 以简化状态机切换测试。</returns>
|
||||
public bool CanTransitionTo(IState next)
|
||||
{
|
||||
_ = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="previous">前一个状态。</param>
|
||||
public void OnEnter(IState? previous)
|
||||
{
|
||||
_ = previous;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出状态时调用。该测试替身不需要额外行为。
|
||||
/// </summary>
|
||||
/// <param name="next">下一个状态。</param>
|
||||
public void OnExit(IState? next)
|
||||
{
|
||||
_ = next;
|
||||
}
|
||||
}
|
||||
59
GFramework.Core.Tests/State/TrackingStateV2.cs
Normal file
59
GFramework.Core.Tests/State/TrackingStateV2.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using GFramework.Core.Abstractions.State;
|
||||
|
||||
namespace GFramework.Core.Tests.State;
|
||||
|
||||
/// <summary>
|
||||
/// 跟踪状态实现类V2版本,用于跟踪状态转换次数。
|
||||
/// </summary>
|
||||
public sealed class TrackingStateV2 : IState
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取进入状态被调用的次数。
|
||||
/// </summary>
|
||||
public int EnterCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取退出状态被调用的次数。
|
||||
/// </summary>
|
||||
public int ExitCallCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取进入此状态的来源状态。
|
||||
/// </summary>
|
||||
public IState? EnterFrom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取从此状态退出的目标状态。
|
||||
/// </summary>
|
||||
public IState? ExitTo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进入当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="from">从哪个状态进入。</param>
|
||||
public void OnEnter(IState? from)
|
||||
{
|
||||
EnterCallCount++;
|
||||
EnterFrom = from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出当前状态时调用的方法。
|
||||
/// </summary>
|
||||
/// <param name="to">退出到哪个状态。</param>
|
||||
public void OnExit(IState? to)
|
||||
{
|
||||
ExitCallCount++;
|
||||
ExitTo = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否可以转换到目标状态。
|
||||
/// </summary>
|
||||
/// <param name="target">目标状态。</param>
|
||||
/// <returns>始终返回 <see langword="true" />。</returns>
|
||||
public bool CanTransitionTo(IState target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用上下文工具类V1
|
||||
/// </summary>
|
||||
public sealed class TestContextUtilityV1 : AbstractContextUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取工具是否已初始化
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取工具是否已销毁
|
||||
/// </summary>
|
||||
public bool Destroyed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取Init方法是否被调用
|
||||
/// </summary>
|
||||
public bool InitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取Logger对象(用于测试)
|
||||
/// </summary>
|
||||
public ILogger? GetLogger()
|
||||
{
|
||||
return Logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化方法
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
Initialized = true;
|
||||
InitCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁方法
|
||||
/// </summary>
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
Destroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用上下文工具类V2,自定义初始化逻辑
|
||||
/// </summary>
|
||||
public sealed class TestContextUtilityV2 : AbstractContextUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取工具是否已初始化
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取工具是否已销毁
|
||||
/// </summary>
|
||||
public bool Destroyed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取自定义初始化是否完成
|
||||
/// </summary>
|
||||
public bool CustomInitializationDone { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化方法(自定义逻辑)
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
Initialized = true;
|
||||
CustomInitializationDone = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁方法
|
||||
/// </summary>
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
Destroyed = true;
|
||||
}
|
||||
}
|
||||
60
GFramework.Core.Tests/Utility/TestContextUtilityV1.cs
Normal file
60
GFramework.Core.Tests/Utility/TestContextUtilityV1.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
using GFramework.Core.Utility;
|
||||
|
||||
namespace GFramework.Core.Tests.Utility;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AbstractContextUtilityTests" /> 提供的基础上下文工具测试桩。
|
||||
/// </summary>
|
||||
public sealed class TestContextUtilityV1 : AbstractContextUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示当前工具是否已完成初始化。
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示当前工具是否已执行销毁逻辑。
|
||||
/// </summary>
|
||||
public bool Destroyed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示测试专用的 <see cref="OnInit" /> 钩子是否已被调用。
|
||||
/// 该标记与 <see cref="Initialized" /> 共享同一执行时机,但单独暴露以便断言钩子本身已运行。
|
||||
/// </summary>
|
||||
public bool InitCalled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取初始化阶段创建的日志记录器,供测试断言使用。
|
||||
/// </summary>
|
||||
/// <returns>初始化后缓存的日志记录器;初始化前返回 <see langword="null" />。</returns>
|
||||
public ILogger? GetLogger()
|
||||
{
|
||||
return Logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录初始化已发生,并标记测试钩子调用状态。
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
Initialized = true;
|
||||
InitCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录销毁流程已运行,供生命周期测试断言使用。
|
||||
/// </summary>
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
Destroyed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置销毁标记,供同一实例的重复生命周期测试在下一轮初始化前清理观测状态。
|
||||
/// </summary>
|
||||
public void ResetDestroyedStateForTest()
|
||||
{
|
||||
Destroyed = false;
|
||||
}
|
||||
}
|
||||
41
GFramework.Core.Tests/Utility/TestContextUtilityV2.cs
Normal file
41
GFramework.Core.Tests/Utility/TestContextUtilityV2.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using GFramework.Core.Utility;
|
||||
|
||||
namespace GFramework.Core.Tests.Utility;
|
||||
|
||||
/// <summary>
|
||||
/// 为 <see cref="AbstractContextUtilityTests" /> 提供的自定义初始化上下文工具测试桩。
|
||||
/// </summary>
|
||||
public sealed class TestContextUtilityV2 : AbstractContextUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示当前工具是否已完成初始化。
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示当前工具是否已执行销毁逻辑。
|
||||
/// </summary>
|
||||
public bool Destroyed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示自定义初始化步骤是否已完成。
|
||||
/// </summary>
|
||||
public bool CustomInitializationDone { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 在基础初始化期间记录自定义初始化步骤已执行。
|
||||
/// </summary>
|
||||
protected override void OnInit()
|
||||
{
|
||||
Initialized = true;
|
||||
CustomInitializationDone = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录销毁流程已运行,供生命周期测试断言使用。
|
||||
/// </summary>
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
Destroyed = true;
|
||||
}
|
||||
}
|
||||
@ -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` 的 `<returns>` 文档
|
||||
- 本轮新增一条精确回归测试,确保底层 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/*` 作为独立高风险波次处理。
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user