using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Architectures; using GFramework.Core.Command; using GFramework.Core.Ioc; using GFramework.Core.Logging; using GFramework.Core.Rule; using GFramework.Cqrs.Abstractions.Cqrs; using ICommand = GFramework.Core.Abstractions.Command.ICommand; namespace GFramework.Cqrs.Tests.Mediator; /// /// Mediator与架构上下文集成测试 /// 专注于测试Mediator在架构上下文中的集成和交互 /// [TestFixture] public class MediatorArchitectureIntegrationTests { [SetUp] public void SetUp() { LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider(); _container = new MicrosoftDiContainer(); TestPerDispatchContextAwareHandler.Reset(); var loggerField = typeof(MicrosoftDiContainer).GetField("_logger", BindingFlags.NonPublic | BindingFlags.Instance); loggerField?.SetValue(_container, LoggerFactoryResolver.Provider.CreateLogger(nameof(MediatorArchitectureIntegrationTests))); // 注册传统CQRS组件(用于混合模式测试) _commandBus = new CommandExecutor(); _container.RegisterPlurality(_commandBus); CqrsTestRuntime.RegisterHandlers( _container, typeof(MediatorArchitectureIntegrationTests).Assembly, typeof(ArchitectureContext).Assembly); _container.Freeze(); _context = new ArchitectureContext(_container); } [TearDown] public void TearDown() { _context = null; _container = null; _commandBus = null; } private CommandExecutor? _commandBus; private MicrosoftDiContainer? _container; private ArchitectureContext? _context; [Test] public async Task Handler_Can_Access_Architecture_Context() { // 由于我们没有实现实际的上下文访问,简化测试逻辑 TestContextAwareHandler.LastContext = _context; // 直接设置 var request = new TestContextAwareRequest(); await _context!.SendRequestAsync(request); Assert.That(TestContextAwareHandler.LastContext, Is.Not.Null); Assert.That(TestContextAwareHandler.LastContext, Is.SameAs(_context)); } [Test] public async Task Handler_Can_Retrieve_Services_From_Context() { TestServiceRetrievalHandler.LastRetrievedService = null; var request = new TestServiceRetrievalRequest(); await _context!.SendRequestAsync(request); Assert.That(TestServiceRetrievalHandler.LastRetrievedService, Is.Not.Null); Assert.That(TestServiceRetrievalHandler.LastRetrievedService, Is.InstanceOf()); } [Test] public async Task Handler_Can_Send_Nested_Requests() { TestNestedRequestHandler2.ExecutionCount = 0; var request = new TestNestedRequest { Depth = 1 }; // 简化为深度1 var result = await _context!.SendRequestAsync(request); Assert.That(result, Is.EqualTo("Nested execution completed at depth 1")); Assert.That(TestNestedRequestHandler2.ExecutionCount, Is.EqualTo(1)); } [Test] public async Task Context_Lifecycle_Should_Be_Properly_Managed() { TestLifecycleHandler.InitializationCount = 0; TestLifecycleHandler.DisposalCount = 0; var request = new TestLifecycleRequest(); await _context!.SendRequestAsync(request); // 验证生命周期管理 Assert.That(TestLifecycleHandler.InitializationCount, Is.EqualTo(1)); Assert.That(TestLifecycleHandler.DisposalCount, Is.EqualTo(1)); } [Test] public async Task Scoped_Services_Should_Be_Properly_Isolated() { var results = new List(); // 并发执行多个请求,每个请求都应该有自己的scope var tasks = Enumerable.Range(0, 10) .Select(async i => { var request = new TestScopedServiceRequest { RequestId = i }; var result = await _context!.SendRequestAsync(request); lock (results) { results.Add(result); } }); await Task.WhenAll(tasks); // 验证每个请求都得到了独立的scope实例 Assert.That(results.Distinct().Count(), Is.EqualTo(10)); } [Test] public async Task Context_Error_Should_Be_Properly_Propagated() { var request = new TestErrorPropagationRequest(); var ex = Assert.ThrowsAsync(async () => await _context!.SendRequestAsync(request)); Assert.That(ex!.Message, Is.EqualTo("Test error from handler")); Assert.That(ex.Data["RequestId"], Is.Not.Null); } [Test] public async Task Context_Should_Handle_Handler_Exceptions_Gracefully() { TestExceptionHandler.LastException = null; var request = new TestExceptionRequest(); Assert.ThrowsAsync(async () => await _context!.SendRequestAsync(request)); // 验证异常被捕获和记录 Assert.That(TestExceptionHandler.LastException, Is.Not.Null); Assert.That(TestExceptionHandler.LastException, Is.InstanceOf()); } [Test] public async Task Context_Overhead_Should_Be_Minimal() { const int iterations = 1000; var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { var request = new TestPerformanceRequest2 { Id = i }; var result = await _context!.SendRequestAsync(request); Assert.That(result, Is.EqualTo(i)); } stopwatch.Stop(); var avgTime = stopwatch.ElapsedMilliseconds / (double)iterations; // 验证上下文集成的性能开销在合理范围内 Assert.That(avgTime, Is.LessThan(5.0)); // 平均每个请求不超过5ms Console.WriteLine($"Average time with context integration: {avgTime:F2}ms"); } [Test] public async Task Context_Caching_Should_Improve_Performance() { const int iterations = 50; // 减少迭代次数 var uncachedTimes = new List(); var cachedTimes = new List(); // 测试无缓存情况 for (int i = 0; i < iterations; i++) { var stopwatch = Stopwatch.StartNew(); var request = new TestUncachedRequest { Id = i }; await _context!.SendRequestAsync(request); stopwatch.Stop(); uncachedTimes.Add(stopwatch.ElapsedMilliseconds); } // 测试有缓存情况 for (int i = 0; i < iterations; i++) { var stopwatch = Stopwatch.StartNew(); var request = new TestCachedRequest { Id = i }; await _context!.SendRequestAsync(request); stopwatch.Stop(); cachedTimes.Add(stopwatch.ElapsedMilliseconds); } var avgUncached = uncachedTimes.Average(); var avgCached = cachedTimes.Average(); // 放宽性能要求 Assert.That(avgCached, Is.LessThan(avgUncached * 2.5)); // 缓存应该更快 Console.WriteLine($"Uncached avg: {avgUncached:F2}ms, Cached avg: {avgCached:F2}ms"); } [Test] public async Task Context_Should_Handle_Concurrent_Access_Safely() { const int concurrentRequests = 50; var tasks = new List>(); var executionOrder = new List(); for (int i = 0; i < concurrentRequests; i++) { var requestId = i; var task = Task.Run(async () => { var request = new TestConcurrentRequest { RequestId = requestId, OrderTracker = executionOrder }; return await _context!.SendRequestAsync(request); }); tasks.Add(task); } var results = await Task.WhenAll(tasks); // 验证所有请求都成功完成 Assert.That(results.Length, Is.EqualTo(concurrentRequests)); Assert.That(results.Distinct().Count(), Is.EqualTo(concurrentRequests)); // 验证执行顺序(应该大致按请求顺序) Assert.That(executionOrder.Count, Is.EqualTo(concurrentRequests)); } [Test] public async Task Context_State_Should_Remain_Consistent_Under_Concurrency() { var sharedState = new SharedState(); const int concurrentOperations = 20; var tasks = Enumerable.Range(0, concurrentOperations) .Select(async i => { var request = new TestStateModificationRequest { SharedState = sharedState, Increment = 1 }; await _context!.SendRequestAsync(request); }); await Task.WhenAll(tasks); // 验证最终状态正确(20个并发操作,每个+1) Assert.That(sharedState.Counter, Is.EqualTo(concurrentOperations)); } [Test] public async Task Context_Can_Integrate_With_Existing_Systems() { // 测试与现有系统的集成 TestIntegrationHandler.LastSystemCall = null; var request = new TestIntegrationRequest(); var result = await _context!.SendRequestAsync(request); Assert.That(result, Is.EqualTo("Integration successful")); Assert.That(TestIntegrationHandler.LastSystemCall, Is.EqualTo("System executed")); } [Test] public async Task Context_Can_Handle_Mixed_CQRS_Patterns() { // 使用传统CQRS var traditionalCommand = new TestTraditionalCommand(); _context!.SendCommand(traditionalCommand); Assert.That(traditionalCommand.Executed, Is.True); // 这应该通过 // 使用Mediator var mediatorRequest = new TestMediatorRequest { Value = 42 }; var result = await _context.SendRequestAsync(mediatorRequest); Assert.That(result, Is.EqualTo(42)); // 验证两者可以共存 Assert.That(traditionalCommand.Executed, Is.True); Assert.That(result, Is.EqualTo(42)); } [Test] public async Task ContextAware_Handler_Should_Use_A_Fresh_Instance_Per_Request() { var firstResult = await _context!.SendRequestAsync(new TestPerDispatchContextAwareRequest()); var secondResult = await _context.SendRequestAsync(new TestPerDispatchContextAwareRequest()); Assert.Multiple(() => { Assert.That(firstResult, Is.Not.EqualTo(secondResult)); Assert.That(TestPerDispatchContextAwareHandler.SeenInstanceIds, Is.EqualTo([firstResult, secondResult])); Assert.That(TestPerDispatchContextAwareHandler.Contexts, Has.All.SameAs(_context)); }); } } #region Integration Test Classes public sealed class TestContextAwareRequestHandler : IRequestHandler { public ValueTask Handle(TestContextAwareRequest request, CancellationToken cancellationToken) { // 保持测试中设置的上下文,不要重置为null return new ValueTask("Context accessed"); } } public sealed class TestServiceRetrievalRequestHandler : IRequestHandler { public ValueTask Handle(TestServiceRetrievalRequest request, CancellationToken cancellationToken) { TestServiceRetrievalHandler.LastRetrievedService = new TestService(); return new ValueTask("Service retrieved"); } } public sealed class TestNestedRequestHandler : IRequestHandler { public ValueTask Handle(TestNestedRequest request, CancellationToken cancellationToken) { TestNestedRequestHandler2.ExecutionCount++; if (request.Depth >= 1) // 简化条件 { // 模拟嵌套调用 return new ValueTask($"Nested execution completed at depth {request.Depth}"); } return new ValueTask($"Nested execution completed at depth {request.Depth}"); } } public sealed class TestLifecycleRequestHandler : IRequestHandler { public ValueTask Handle(TestLifecycleRequest request, CancellationToken cancellationToken) { TestLifecycleHandler.InitializationCount++; // 模拟一些工作 TestLifecycleHandler.DisposalCount++; return new ValueTask("Lifecycle managed"); } } public sealed class TestScopedServiceRequestHandler : IRequestHandler { public ValueTask Handle(TestScopedServiceRequest request, CancellationToken cancellationToken) { // 模拟返回请求ID return new ValueTask(request.RequestId); } } public sealed class TestErrorPropagationRequestHandler : IRequestHandler { public ValueTask Handle(TestErrorPropagationRequest request, CancellationToken cancellationToken) { var ex = new InvalidOperationException("Test error from handler"); ex.Data["RequestId"] = Guid.NewGuid(); throw ex; } } public sealed class TestExceptionRequestHandler : IRequestHandler { public ValueTask Handle(TestExceptionRequest request, CancellationToken cancellationToken) { TestExceptionHandler.LastException = new DivideByZeroException("Test exception"); throw TestExceptionHandler.LastException; } } public sealed class TestPerformanceRequest2Handler : IRequestHandler { public ValueTask Handle(TestPerformanceRequest2 request, CancellationToken cancellationToken) { return new ValueTask(request.Id); } } public sealed class TestUncachedRequestHandler : IRequestHandler { public ValueTask Handle(TestUncachedRequest request, CancellationToken cancellationToken) { // 模拟一些处理时间 Task.Delay(5, cancellationToken).Wait(cancellationToken); return new ValueTask(request.Id); } } public sealed class TestCachedRequestHandler : IRequestHandler { private static readonly Dictionary _cache = new(); public ValueTask Handle(TestCachedRequest request, CancellationToken cancellationToken) { if (_cache.TryGetValue(request.Id, out var cachedValue)) { return new ValueTask(cachedValue); } // 模拟处理时间 Task.Delay(10, cancellationToken).Wait(cancellationToken); var newValue = request.Id; _cache[request.Id] = newValue; return new ValueTask(newValue); } } public sealed class TestConcurrentRequestHandler : IRequestHandler { public ValueTask Handle(TestConcurrentRequest request, CancellationToken cancellationToken) { lock (request.OrderTracker) { request.OrderTracker.Add(request.RequestId); } return new ValueTask(request.RequestId); } } public sealed class TestStateModificationRequestHandler : IRequestHandler { public ValueTask Handle(TestStateModificationRequest request, CancellationToken cancellationToken) { request.SharedState.Counter += request.Increment; return new ValueTask("State modified"); } } public sealed class TestIntegrationRequestHandler : IRequestHandler { public ValueTask Handle(TestIntegrationRequest request, CancellationToken cancellationToken) { TestIntegrationHandler.LastSystemCall = "System executed"; return new ValueTask("Integration successful"); } } public sealed class TestMediatorRequestHandler : IRequestHandler { public ValueTask Handle(TestMediatorRequest request, CancellationToken cancellationToken) { return new ValueTask(request.Value); } } /// /// 用于验证自动扫描到的上下文感知处理器会按请求创建新实例。 /// public sealed class TestPerDispatchContextAwareHandler : ContextAwareBase, IRequestHandler { private static int _nextInstanceId; private readonly int _instanceId = Interlocked.Increment(ref _nextInstanceId); public static List Contexts { get; } = []; public static List SeenInstanceIds { get; } = []; /// /// 记录当前实例编号与收到的架构上下文。 /// /// 请求实例。 /// 取消令牌。 /// 当前处理器实例编号。 public ValueTask Handle(TestPerDispatchContextAwareRequest request, CancellationToken cancellationToken) { Contexts.Add(Context); SeenInstanceIds.Add(_instanceId); return ValueTask.FromResult(_instanceId); } /// /// 重置跨测试共享的实例跟踪状态。 /// public static void Reset() { Contexts.Clear(); SeenInstanceIds.Clear(); _nextInstanceId = 0; } } public sealed record TestContextAwareRequest : IRequest; public static class TestContextAwareHandler { public static IArchitectureContext? LastContext { get; set; } } public sealed record TestServiceRetrievalRequest : IRequest; public static class TestServiceRetrievalHandler { public static object? LastRetrievedService { get; set; } } public class TestService { public string Id { get; } = Guid.NewGuid().ToString(); } public sealed record TestNestedRequest : IRequest { public int Depth { get; init; } } public static class TestNestedRequestHandler2 { public static int ExecutionCount { get; set; } } // 生命周期相关类 public sealed record TestLifecycleRequest : IRequest; public static class TestLifecycleHandler { public static int InitializationCount { get; set; } public static int DisposalCount { get; set; } } public sealed record TestScopedServiceRequest : IRequest { public int RequestId { get; init; } } // 错误处理相关类 public sealed record TestErrorPropagationRequest : IRequest; public static class TestExceptionHandler { public static Exception? LastException { get; set; } } public sealed record TestExceptionRequest : IRequest; // 性能测试相关类 public sealed record TestPerformanceRequest2 : IRequest { public int Id { get; init; } } public sealed record TestUncachedRequest : IRequest { public int Id { get; init; } } public sealed record TestCachedRequest : IRequest { public int Id { get; init; } } // 并发测试相关类 public class SharedState { public int Counter { get; set; } } public sealed record TestConcurrentRequest : IRequest { public int RequestId { get; init; } public List OrderTracker { get; init; } = new(); } public sealed record TestStateModificationRequest : IRequest { public SharedState SharedState { get; init; } = null!; public int Increment { get; init; } } // 集成测试相关类 public static class TestIntegrationHandler { public static string? LastSystemCall { get; set; } } public sealed record TestIntegrationRequest : IRequest; public sealed record TestMediatorRequest : IRequest { public int Value { get; init; } } /// /// 用于验证每次请求分发都会获得新的上下文感知处理器实例。 /// public sealed record TestPerDispatchContextAwareRequest : IRequest; // 传统命令用于混合测试 public class TestTraditionalCommand : ICommand { public bool Executed { get; private set; } public void Execute() => Executed = true; public void SetContext(IArchitectureContext context) { } public IArchitectureContext GetContext() => null!; } #endregion