diff --git a/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs index 35f15736..82bf3253 100644 --- a/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs +++ b/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs @@ -13,6 +13,24 @@ namespace GFramework.Cqrs.Tests.Cqrs; [TestFixture] internal sealed class CqrsRegistrationServiceTests { + /// + /// 验证空程序集输入不会触发底层注册,也不会产生重复跳过日志。 + /// + [Test] + public void RegisterHandlers_Should_Not_Invoke_Registrar_When_Assemblies_Are_Empty() + { + var logger = new TestLogger("DefaultCqrsRegistrationService", LogLevel.Debug); + var registrar = new Mock(MockBehavior.Strict); + var service = CqrsRuntimeFactory.CreateRegistrationService(registrar.Object, logger); + + service.RegisterHandlers([]); + + registrar.Verify( + static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()), + Times.Never); + Assert.That(logger.Logs, Has.Count.EqualTo(0)); + } + /// /// 验证同一次调用内出现重复程序集键时,底层注册器只会接收到一次注册请求。 /// @@ -87,6 +105,82 @@ internal sealed class CqrsRegistrationServiceTests }); } + /// + /// 验证协调器会忽略空项,并按稳定程序集键排序后仅注册当前调用内的唯一程序集。 + /// + [Test] + public void RegisterHandlers_Should_Ignore_Null_Entries_And_Register_Unique_Assemblies_In_Stable_Key_Order() + { + var logger = new TestLogger("DefaultCqrsRegistrationService", LogLevel.Debug); + var registrar = new Mock(MockBehavior.Strict); + var assemblyC = CreateAssembly("GFramework.Cqrs.Tests.Sorting.C, Version=1.0.0.0"); + var assemblyA = CreateAssembly("GFramework.Cqrs.Tests.Sorting.A, Version=1.0.0.0"); + var duplicateAssemblyA = CreateAssembly("GFramework.Cqrs.Tests.Sorting.A, Version=1.0.0.0"); + var assemblyB = CreateAssembly("GFramework.Cqrs.Tests.Sorting.B, Version=1.0.0.0"); + var registeredAssemblies = new List(); + + registrar + .Setup(static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>())) + .Callback>(assemblies => registeredAssemblies.AddRange(assemblies)); + + var service = CqrsRuntimeFactory.CreateRegistrationService(registrar.Object, logger); + + service.RegisterHandlers([assemblyC.Object, null!, assemblyA.Object, duplicateAssemblyA.Object, assemblyB.Object, null!]); + + registrar.Verify( + static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()), + Times.Exactly(3)); + Assert.Multiple(() => + { + Assert.That( + registeredAssemblies, + Is.EqualTo([assemblyA.Object, assemblyB.Object, assemblyC.Object])); + Assert.That(logger.Logs, Has.Count.EqualTo(0)); + }); + } + + /// + /// 验证跨调用遇到已注册程序集键时,协调器会跳过重复项,同时继续按稳定程序集键顺序处理剩余新程序集。 + /// + [Test] + public void RegisterHandlers_Should_Skip_Previously_Registered_Keys_And_Keep_Stable_Order_For_Remaining_Assemblies() + { + var logger = new TestLogger("DefaultCqrsRegistrationService", LogLevel.Debug); + var registrar = new Mock(MockBehavior.Strict); + var firstAssembly = CreateAssembly("GFramework.Cqrs.Tests.Sorting.B, Version=1.0.0.0"); + var duplicateAssembly = CreateAssembly("GFramework.Cqrs.Tests.Sorting.B, Version=1.0.0.0"); + var assemblyC = CreateAssembly("GFramework.Cqrs.Tests.Sorting.C, Version=1.0.0.0"); + var assemblyA = CreateAssembly("GFramework.Cqrs.Tests.Sorting.A, Version=1.0.0.0"); + var registeredAssemblies = new List(); + + registrar + .Setup(static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>())) + .Callback>(assemblies => registeredAssemblies.AddRange(assemblies)); + + var service = CqrsRuntimeFactory.CreateRegistrationService(registrar.Object, logger); + + service.RegisterHandlers([firstAssembly.Object]); + service.RegisterHandlers([assemblyC.Object, duplicateAssembly.Object, assemblyA.Object]); + + registrar.Verify( + static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()), + Times.Exactly(3)); + Assert.Multiple(() => + { + Assert.That( + registeredAssemblies, + Is.EqualTo([firstAssembly.Object, assemblyA.Object, assemblyC.Object])); + var debugMessages = logger.Logs + .Where(static log => log.Level == LogLevel.Debug) + .Select(static log => log.Message) + .ToArray(); + Assert.That(debugMessages, Has.Length.EqualTo(1)); + Assert.That( + debugMessages[0], + Does.Contain("GFramework.Cqrs.Tests.Sorting.B, Version=1.0.0.0")); + }); + } + /// /// 验证当 缺失时,协调器会退化到 作为稳定程序集键。 ///