From 226c0b3b498701857fa7a0d8a68a808da33093b1 Mon Sep 17 00:00:00 2001
From: gewuyou <95328647+GeWuYou@users.noreply.github.com>
Date: Wed, 29 Apr 2026 17:52:52 +0800
Subject: [PATCH] =?UTF-8?q?test(cqrs):=20=E8=A1=A5=E5=85=85=E6=B3=A8?=
=?UTF-8?q?=E5=86=8C=E6=9C=8D=E5=8A=A1=E7=A8=8B=E5=BA=8F=E9=9B=86=E5=8E=BB?=
=?UTF-8?q?=E9=87=8D=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 DefaultCqrsRegistrationService 的独立测试文件,覆盖同次调用内的重复程序集键去重行为
- 验证跨两次调用重复程序集键时会跳过注册并写入 debug 日志
---
.../Cqrs/CqrsRegistrationServiceTests.cs | 96 +++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs
diff --git a/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs
new file mode 100644
index 00000000..b8b03b1c
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/CqrsRegistrationServiceTests.cs
@@ -0,0 +1,96 @@
+using GFramework.Core.Abstractions.Logging;
+using GFramework.Cqrs.Abstractions.Cqrs;
+using GFramework.Cqrs.Tests.Logging;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 验证 CQRS 程序集注册协调器在程序集键去重层面的可观察行为。
+///
+[TestFixture]
+internal sealed class CqrsRegistrationServiceTests
+{
+ ///
+ /// 验证同一次调用内出现重复程序集键时,底层注册器只会接收到一次注册请求。
+ ///
+ [Test]
+ public void RegisterHandlers_Should_Register_Duplicate_Assembly_Key_Only_Once_Per_Call()
+ {
+ var logger = new TestLogger("DefaultCqrsRegistrationService", LogLevel.Debug);
+ var registrar = new Mock(MockBehavior.Strict);
+ var duplicateAssemblyA = CreateAssembly("GFramework.Cqrs.Tests.DuplicateAssembly, Version=1.0.0.0");
+ var duplicateAssemblyB = CreateAssembly("GFramework.Cqrs.Tests.DuplicateAssembly, Version=1.0.0.0");
+ var expectedAssembly = duplicateAssemblyA.Object;
+ IEnumerable? registeredAssemblies = null;
+
+ registrar
+ .Setup(static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()))
+ .Callback>(assemblies => registeredAssemblies = assemblies.ToArray());
+
+ var service = CqrsRuntimeFactory.CreateRegistrationService(registrar.Object, logger);
+
+ service.RegisterHandlers([duplicateAssemblyA.Object, duplicateAssemblyB.Object]);
+
+ registrar.Verify(
+ static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()),
+ Times.Once);
+ Assert.Multiple(() =>
+ {
+ Assert.That(registeredAssemblies, Is.Not.Null);
+ Assert.That(registeredAssemblies, Is.EqualTo([expectedAssembly]));
+ Assert.That(logger.Logs, Has.Count.EqualTo(0));
+ });
+ }
+
+ ///
+ /// 验证跨两次调用重复程序集键时,协调器会跳过重复注册并写入 debug 日志。
+ ///
+ [Test]
+ public void RegisterHandlers_Should_Skip_Already_Registered_Assembly_Key_Across_Calls_And_Log_Debug_Message()
+ {
+ var logger = new TestLogger("DefaultCqrsRegistrationService", LogLevel.Debug);
+ var registrar = new Mock(MockBehavior.Strict);
+ var firstAssembly = CreateAssembly("GFramework.Cqrs.Tests.RegisteredAssembly, Version=1.0.0.0");
+ var secondAssembly = CreateAssembly("GFramework.Cqrs.Tests.RegisteredAssembly, Version=1.0.0.0");
+ IEnumerable? registeredAssemblies = null;
+
+ registrar
+ .Setup(static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()))
+ .Callback>(assemblies => registeredAssemblies = assemblies.ToArray());
+
+ var service = CqrsRuntimeFactory.CreateRegistrationService(registrar.Object, logger);
+
+ service.RegisterHandlers([firstAssembly.Object]);
+ service.RegisterHandlers([secondAssembly.Object]);
+
+ registrar.Verify(
+ static currentRegistrar => currentRegistrar.RegisterHandlers(It.IsAny>()),
+ Times.Once);
+ Assert.Multiple(() =>
+ {
+ Assert.That(registeredAssemblies, Is.EqualTo([firstAssembly.Object]));
+ Assert.That(
+ logger.Logs.Where(static log => log.Level == LogLevel.Debug).Select(static log => log.Message),
+ Is.EqualTo(
+ [
+ "Skipping CQRS handler registration for assembly " +
+ "GFramework.Cqrs.Tests.RegisteredAssembly, Version=1.0.0.0 because it was already registered."
+ ]));
+ });
+ }
+
+ ///
+ /// 创建一个带稳定程序集键的程序集 mock,用于模拟不同 实例表示同一程序集的场景。
+ ///
+ /// 要返回的程序集完整名称。
+ /// 配置好完整名称的程序集 mock。
+ private static Mock CreateAssembly(string assemblyFullName)
+ {
+ var assembly = new Mock();
+ assembly
+ .SetupGet(static currentAssembly => currentAssembly.FullName)
+ .Returns(assemblyFullName);
+
+ return assembly;
+ }
+}