From 36596210ff89f77fc991109deac9e2d7ffd5587e Mon Sep 17 00:00:00 2001
From: gewuyou <95328647+GeWuYou@users.noreply.github.com>
Date: Wed, 29 Apr 2026 17:49:46 +0800
Subject: [PATCH] =?UTF-8?q?test(cqrs):=20=E6=96=B0=E5=A2=9E=20ReflectionFa?=
=?UTF-8?q?llbackAttribute=20=E5=90=88=E5=90=8C=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 CqrsReflectionFallbackAttribute 的叶子级合同测试,覆盖旧版 marker 语义
- 补充字符串与 Type 输入的过滤、去重、排序归一化断言
- 验证空参数数组保护,固定 runtime 可依赖的 attribute 元数据边界
---
.../CqrsReflectionFallbackAttributeTests.cs | 97 +++++++++++++++++++
1 file changed, 97 insertions(+)
create mode 100644 GFramework.Cqrs.Tests/Cqrs/CqrsReflectionFallbackAttributeTests.cs
diff --git a/GFramework.Cqrs.Tests/Cqrs/CqrsReflectionFallbackAttributeTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsReflectionFallbackAttributeTests.cs
new file mode 100644
index 00000000..53bb2988
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/CqrsReflectionFallbackAttributeTests.cs
@@ -0,0 +1,97 @@
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 验证 公开构造器的归一化合同,
+/// 以固定 runtime 读取程序集级 fallback 元数据时可依赖的可观察语义。
+///
+[TestFixture]
+internal sealed class CqrsReflectionFallbackAttributeTests
+{
+ ///
+ /// 验证无参构造器会保留旧版 marker 语义,并暴露空的 fallback 集合。
+ ///
+ [Test]
+ public void Constructor_Without_Arguments_Should_Expose_Empty_Fallback_Collections()
+ {
+ var attribute = new CqrsReflectionFallbackAttribute();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(attribute.FallbackHandlerTypeNames, Is.Empty);
+ Assert.That(attribute.FallbackHandlerTypes, Is.Empty);
+ });
+ }
+
+ ///
+ /// 验证字符串名称重载会过滤空白项,并按序号稳定去重排序,
+ /// 确保 runtime 后续读取到的名称清单不依赖调用端输入顺序。
+ ///
+ [Test]
+ public void Constructor_With_Type_Names_Should_Normalize_By_Filtering_Deduplicating_And_Sorting()
+ {
+ var attribute = new CqrsReflectionFallbackAttribute(
+ "Zeta.Handler",
+ " ",
+ "Alpha.Handler",
+ "Zeta.Handler",
+ string.Empty,
+ "Beta.Handler",
+ "Alpha.Handler");
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(
+ attribute.FallbackHandlerTypeNames,
+ Is.EqualTo(["Alpha.Handler", "Beta.Handler", "Zeta.Handler"]));
+ Assert.That(attribute.FallbackHandlerTypes, Is.Empty);
+ });
+ }
+
+ ///
+ /// 验证字符串名称重载收到 参数数组时会立即拒绝,
+ /// 避免 runtime 在读取程序集元数据时延迟暴露无效状态。
+ ///
+ [Test]
+ public void Constructor_With_Null_Type_Name_Array_Should_Throw_ArgumentNullException()
+ {
+ Assert.That(
+ () => _ = new CqrsReflectionFallbackAttribute((string[])null!),
+ Throws.ArgumentNullException);
+ }
+
+ ///
+ /// 验证 重载会过滤空引用,并按稳定名称顺序去重,
+ /// 确保后续 fallback 补扫不会因为重复输入或反射枚举顺序产生非确定性。
+ ///
+ [Test]
+ public void Constructor_With_Types_Should_Normalize_By_Filtering_Deduplicating_And_Sorting()
+ {
+ var attribute = new CqrsReflectionFallbackAttribute(
+ typeof(string),
+ null!,
+ typeof(Uri),
+ typeof(string),
+ typeof(Version));
+
+ // 这里按 FullName 的 Ordinal 顺序断言,固定该 attribute 对 runtime 暴露的元数据排序合同。
+ Assert.Multiple(() =>
+ {
+ Assert.That(
+ attribute.FallbackHandlerTypes,
+ Is.EqualTo([typeof(string), typeof(Uri), typeof(Version)]));
+ Assert.That(attribute.FallbackHandlerTypeNames, Is.Empty);
+ });
+ }
+
+ ///
+ /// 验证 重载收到 参数数组时会立即拒绝,
+ /// 从而维持 attribute 元数据的最小有效性边界。
+ ///
+ [Test]
+ public void Constructor_With_Null_Type_Array_Should_Throw_ArgumentNullException()
+ {
+ Assert.That(
+ () => _ = new CqrsReflectionFallbackAttribute((Type[])null!),
+ Throws.ArgumentNullException);
+ }
+}