From e1af8ac833c368d4fd0d610658a385883eaae6ee Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:24:22 +0800 Subject: [PATCH] =?UTF-8?q?test(cqrs):=20=E6=94=B6=E5=8F=A3=E9=AB=98?= =?UTF-8?q?=E7=BA=A7=E7=89=B9=E6=80=A7=E6=B5=8B=E8=AF=95=E7=9A=84CQRS?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重命名高级特性测试类、命名空间与文件路径,统一到 CQRS 与 ArchitectureContext 语义 - 更新测试方法名、中文注释与日志器名称,移除残留的 Mediator 命名 - 补充当前测试文件内辅助类型的 XML 文档,保持测试行为不变 --- ...chitectureContextAdvancedFeaturesTests.cs} | 221 ++++++++++++++++-- 1 file changed, 198 insertions(+), 23 deletions(-) rename GFramework.Cqrs.Tests/{Mediator/MediatorAdvancedFeaturesTests.cs => Cqrs/CqrsArchitectureContextAdvancedFeaturesTests.cs} (68%) diff --git a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsArchitectureContextAdvancedFeaturesTests.cs similarity index 68% rename from GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs rename to GFramework.Cqrs.Tests/Cqrs/CqrsArchitectureContextAdvancedFeaturesTests.cs index d8e9de59..05674a7b 100644 --- a/GFramework.Cqrs.Tests/Mediator/MediatorAdvancedFeaturesTests.cs +++ b/GFramework.Cqrs.Tests/Cqrs/CqrsArchitectureContextAdvancedFeaturesTests.cs @@ -4,15 +4,20 @@ using GFramework.Core.Ioc; using GFramework.Core.Logging; using GFramework.Cqrs.Abstractions.Cqrs; -namespace GFramework.Cqrs.Tests.Mediator; +namespace GFramework.Cqrs.Tests.Cqrs; /// -/// Mediator高级特性专项测试 -/// 专注于测试Mediator框架的高级功能和边界场景 +/// 验证 CQRS 请求通过 分发时的高级行为与边界场景。 /// [TestFixture] -public class MediatorAdvancedFeaturesTests +internal sealed class CqrsArchitectureContextAdvancedFeaturesTests { + private MicrosoftDiContainer? _container; + private ArchitectureContext? _context; + + /// + /// 初始化测试容器、日志器和 CQRS 处理器注册表。 + /// [SetUp] public void SetUp() { @@ -23,17 +28,20 @@ public class MediatorAdvancedFeaturesTests var loggerField = typeof(MicrosoftDiContainer).GetField("_logger", BindingFlags.NonPublic | BindingFlags.Instance); loggerField?.SetValue(_container, - LoggerFactoryResolver.Provider.CreateLogger(nameof(MediatorAdvancedFeaturesTests))); + LoggerFactoryResolver.Provider.CreateLogger(nameof(CqrsArchitectureContextAdvancedFeaturesTests))); CqrsTestRuntime.RegisterHandlers( _container, - typeof(MediatorAdvancedFeaturesTests).Assembly, + typeof(CqrsArchitectureContextAdvancedFeaturesTests).Assembly, typeof(ArchitectureContext).Assembly); _container.Freeze(); _context = new ArchitectureContext(_container); } + /// + /// 释放当前测试用到的上下文和容器引用。 + /// [TearDown] public void TearDown() { @@ -41,11 +49,9 @@ public class MediatorAdvancedFeaturesTests _container = null; } - private MicrosoftDiContainer? _container; - - private ArchitectureContext? _context; - - + /// + /// 验证请求验证逻辑会阻止无效输入继续进入 CQRS 处理流程。 + /// [Test] public async Task Request_With_Validation_Behavior_Should_Validate_Input() { @@ -68,8 +74,11 @@ public class MediatorAdvancedFeaturesTests Assert.That(TestRetryBehavior.AttemptCount, Is.EqualTo(1)); } + /// + /// 验证高并发 CQRS 请求可以在合理时间内全部完成。 + /// [Test] - public async Task High_Concurrency_Mediator_Requests_Should_Handle_Efficiently() + public async Task High_Concurrency_Cqrs_Requests_Should_Handle_Efficiently() { const int concurrentRequests = 100; var tasks = new List>(); @@ -93,6 +102,9 @@ public class MediatorAdvancedFeaturesTests Assert.That(stopwatch.ElapsedMilliseconds, Is.LessThan(5000)); // 5秒内完成 } + /// + /// 验证大批量请求下的内存占用不会出现明显泄漏。 + /// [Test] public async Task Memory_Usage_Should_Remain_Stable_Under_Heavy_Load() { @@ -132,6 +144,9 @@ public class MediatorAdvancedFeaturesTests Assert.That(TestTransientErrorHandler.ErrorCount, Is.EqualTo(0)); } + /// + /// 验证断路器在持续失败后会快速拒绝后续请求。 + /// [Test] public async Task Circuit_Breaker_Should_Prevent_Cascading_Failures() { @@ -160,6 +175,9 @@ public class MediatorAdvancedFeaturesTests Assert.That(stopwatch.ElapsedMilliseconds, Is.LessThan(100)); } + /// + /// 验证多步 Saga 请求在全部成功时会保持一致的完成状态。 + /// [Test] public async Task Saga_Pattern_With_Multiple_Requests_Should_Maintain_Consistency() { @@ -182,6 +200,9 @@ public class MediatorAdvancedFeaturesTests Assert.That(sagaData.IsCompleted, Is.True); } + /// + /// 验证 Saga 在中途失败时会触发既有步骤的补偿逻辑。 + /// [Test] public async Task Saga_With_Failure_Should_Rollback_Correctly() { @@ -205,6 +226,9 @@ public class MediatorAdvancedFeaturesTests Assert.That(sagaData.IsCompleted, Is.False); } + /// + /// 验证请求链可以在同一架构上下文中顺序完成。 + /// [Test] public async Task Request_Chaining_With_Dependencies_Should_Work_Correctly() { @@ -213,8 +237,11 @@ public class MediatorAdvancedFeaturesTests Assert.That(chainResult, Is.EqualTo("Chain completed: Step1 -> Step2 -> Step3")); } + /// + /// 验证 CQRS 请求依赖外部服务时会正确传播取消超时。 + /// [Test] - public async Task Mediator_With_External_Service_Dependency_Should_Handle_Timeouts() + public async Task Cqrs_With_External_Service_Dependency_Should_Handle_Timeouts() { using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); var request = new TestExternalServiceRequest { TimeoutMs = 1000 }; @@ -223,8 +250,11 @@ public class MediatorAdvancedFeaturesTests await _context!.SendRequestAsync(request, cts.Token).ConfigureAwait(false)); } + /// + /// 验证 CQRS 请求封装数据库写入时仍能保持事务语义上的可观察结果。 + /// [Test] - public async Task Mediator_With_Database_Operations_Should_Handle_Transactions() + public async Task Cqrs_With_Database_Operations_Should_Handle_Transactions() { var testData = new List(); var request = new TestDatabaseRequest { Data = "test data", Storage = testData }; @@ -236,12 +266,16 @@ public class MediatorAdvancedFeaturesTests } } -// 这些高级特性测试需要把一组仅供当前文件使用的辅助类型共置,避免拆成多个噪声文件。 +// 这些 CQRS/ArchitectureContext 高级场景测试需要把一组仅供当前文件使用的辅助类型共置,避免拆成多个噪声文件。 #pragma warning disable MA0048 #region Advanced Test Classes +/// +/// 处理重试请求,并在达到成功条件前累积尝试次数。 +/// public sealed class TestRetryRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestRetryRequest request, CancellationToken cancellationToken) { TestRetryBehavior.AttemptCount++; @@ -255,8 +289,12 @@ public sealed class TestRetryRequestHandler : IRequestHandler +/// 处理瞬态错误请求,并在配置次数内模拟失败。 +/// public sealed class TestTransientErrorRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestTransientErrorRequest request, CancellationToken cancellationToken) { // 只有在MaxErrors > 0时才增加计数器 @@ -274,8 +312,12 @@ public sealed class TestTransientErrorRequestHandler : IRequestHandler +/// 处理断路器请求,并根据失败阈值切换断路器状态。 +/// public sealed class TestCircuitBreakerRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestCircuitBreakerRequest request, CancellationToken cancellationToken) { // 检查断路器状态 @@ -302,8 +344,12 @@ public sealed class TestCircuitBreakerRequestHandler : IRequestHandler +/// 处理 Saga 步骤请求,并在失败时记录补偿步骤。 +/// public sealed class TestSagaStepRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestSagaStepRequest request, CancellationToken cancellationToken) { if (request.ShouldFail && request.Step == 2) @@ -328,8 +374,12 @@ public sealed class TestSagaStepRequestHandler : IRequestHandler +/// 处理链式请求,并返回预定义的链路完成结果。 +/// public sealed class TestChainStartRequestHandler : IRequestHandler { + /// public async ValueTask Handle(TestChainStartRequest request, CancellationToken cancellationToken) { // 模拟链式调用 @@ -338,8 +388,12 @@ public sealed class TestChainStartRequestHandler : IRequestHandler +/// 处理外部服务请求,并通过延时模拟超时场景。 +/// public sealed class TestExternalServiceRequestHandler : IRequestHandler { + /// public async ValueTask Handle(TestExternalServiceRequest request, CancellationToken cancellationToken) { await Task.Delay(request.TimeoutMs, cancellationToken).ConfigureAwait(false); @@ -348,8 +402,12 @@ public sealed class TestExternalServiceRequestHandler : IRequestHandler +/// 处理数据库请求,并把输入数据写入模拟存储集合。 +/// public sealed class TestDatabaseRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestDatabaseRequest request, CancellationToken cancellationToken) { request.Storage.Add(request.Data); @@ -357,26 +415,46 @@ public sealed class TestDatabaseRequestHandler : IRequestHandler +/// 表示用于简单行为验证的测试请求。 +/// public sealed record TestBehaviorRequest : IRequest { + /// + /// 获取或初始化要原样返回的消息内容。 + /// public string Message { get; init; } = string.Empty; } +/// +/// 处理简单行为请求,并回显请求消息。 +/// public sealed class TestBehaviorRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestBehaviorRequest request, CancellationToken cancellationToken) { return new ValueTask(request.Message); } } +/// +/// 表示带输入校验约束的测试请求。 +/// public sealed record TestValidatedRequest : IRequest { + /// + /// 获取或初始化要验证的整数值。 + /// public int Value { get; init; } } +/// +/// 处理带校验的请求,并在输入无效时抛出异常。 +/// public sealed class TestValidatedRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestValidatedRequest request, CancellationToken cancellationToken) { // 验证输入 @@ -389,25 +467,50 @@ public sealed class TestValidatedRequestHandler : IRequestHandler +/// 表示需要在若干次失败后才能成功的重试测试请求。 +/// public sealed record TestRetryRequest : IRequest { + /// + /// 获取或初始化在返回成功前应模拟的失败次数。 + /// public int ShouldFailTimes { get; init; } } +/// +/// 保存重试测试的共享计数状态。 +/// public static class TestRetryBehavior { + /// + /// 获取或设置当前请求处理期间累计的尝试次数。 + /// public static int AttemptCount { get; set; } } -// 性能测试相关类 +/// +/// 表示用于并发与性能验证的测试请求。 +/// public sealed record TestPerformanceRequest : IRequest { + /// + /// 获取或初始化请求的标识值。 + /// public int Id { get; init; } + + /// + /// 获取或初始化模拟处理延时,单位为毫秒。 + /// public int ProcessingTimeMs { get; init; } } +/// +/// 处理性能请求,并在延时后返回请求标识。 +/// public sealed class TestPerformanceRequestHandler : IRequestHandler { + /// public async ValueTask Handle(TestPerformanceRequest request, CancellationToken cancellationToken) { await Task.Delay(request.ProcessingTimeMs, cancellationToken).ConfigureAwait(false); @@ -415,13 +518,23 @@ public sealed class TestPerformanceRequestHandler : IRequestHandler +/// 表示用于内存占用验证的测试请求。 +/// public sealed record TestMemoryRequest : IRequest { + /// + /// 获取或初始化用于模拟负载的数据内容。 + /// public string Data { get; init; } = string.Empty; } +/// +/// 处理内存测试请求,并在不保留额外引用的前提下制造短期分配。 +/// public sealed class TestMemoryRequestHandler : IRequestHandler { + /// public ValueTask Handle(TestMemoryRequest request, CancellationToken cancellationToken) { // 模拟内存使用 @@ -430,25 +543,50 @@ public sealed class TestMemoryRequestHandler : IRequestHandler +/// 保存瞬态错误测试的共享计数状态。 +/// public static class TestTransientErrorHandler { + /// + /// 获取或设置当前已模拟的错误次数。 + /// public static int ErrorCount { get; set; } } +/// +/// 表示用于瞬态错误场景的测试请求。 +/// public sealed record TestTransientErrorRequest : IRequest { + /// + /// 获取或初始化允许连续抛出的最大错误次数。 + /// public int MaxErrors { get; init; } } +/// +/// 保存断路器场景的共享测试状态。 +/// public static class TestCircuitBreakerHandler { + /// + /// 获取或设置当前累计的失败次数。 + /// public static int FailureCount { get; set; } + + /// + /// 获取或设置当前累计的成功次数。 + /// public static int SuccessCount { get; set; } + + /// + /// 获取或设置断路器是否已处于打开状态。 + /// public static bool CircuitOpen { get; set; } /// - /// 重置断路器测试状态,避免静态字段在测试之间互相污染。 + /// 重置断路器测试状态,避免静态字段在测试之间互相污染。 /// public static void Reset() { @@ -458,50 +596,87 @@ public static class TestCircuitBreakerHandler } } +/// +/// 表示用于断路器场景的测试请求。 +/// public sealed record TestCircuitBreakerRequest : IRequest { + /// + /// 获取或初始化当前请求是否应主动模拟失败。 + /// public bool ShouldFail { get; init; } } -// 复杂场景相关类 +/// +/// 保存 Saga 执行与补偿过程中的共享状态。 +/// public class SagaData { /// - /// 获取 Saga 已成功执行的步骤集合。 + /// 获取 Saga 已成功执行的步骤集合。 /// public IList CompletedSteps { get; } = new List(); /// - /// 获取 Saga 失败后已执行补偿的步骤集合。 + /// 获取 Saga 失败后已执行补偿的步骤集合。 /// public IList CompensatedSteps { get; } = new List(); /// - /// 获取或设置 Saga 是否已经完整结束。 + /// 获取或设置 Saga 是否已经完整结束。 /// public bool IsCompleted { get; set; } } +/// +/// 表示 Saga 中单个步骤的测试请求。 +/// public sealed record TestSagaStepRequest : IRequest { + /// + /// 获取或初始化当前要执行的 Saga 步骤编号。 + /// public int Step { get; init; } + + /// + /// 获取或初始化当前 Saga 使用的共享状态对象。 + /// public SagaData SagaData { get; init; } = null!; + + /// + /// 获取或初始化当前步骤是否应模拟失败。 + /// public bool ShouldFail { get; init; } } +/// +/// 表示用于链式请求场景的起始请求。 +/// public sealed record TestChainStartRequest : IRequest; +/// +/// 表示依赖外部服务响应时间的测试请求。 +/// public sealed record TestExternalServiceRequest : IRequest { + /// + /// 获取或初始化模拟外部服务所需的响应时长,单位为毫秒。 + /// public int TimeoutMs { get; init; } } +/// +/// 表示用于模拟数据库写入的测试请求。 +/// public sealed record TestDatabaseRequest : IRequest { + /// + /// 获取或初始化要写入存储集合的数据内容。 + /// public string Data { get; init; } = string.Empty; /// - /// 获取或初始化用于模拟数据库写入的可变存储集合,同时避免泄漏具体集合实现。 + /// 获取或初始化用于模拟数据库写入的可变存储集合,同时避免泄漏具体集合实现。 /// public IList Storage { get; init; } = new List(); }