A:common基础功能及测试

This commit is contained in:
jimmy committed 2025-11-14 10:22:34 +08:00
1 parent 9ffa70acde
commit 237cbd8788
11 files changed
+5929 -32

No files matched your search

+632
View File
@@ -0,0 +1,632 @@
using Common.ExpandFun;
namespace Common.Test;
/// <summary>
/// CollectionExpand 集合扩展测试
/// 展示分页、树形结构、批处理等集合操作功能
/// </summary>
[TestClass]
public class CollectionExpandTests
{
#region 测试数据类
private class TestItem
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int? ParentId { get; set; }
}
#endregion
#region 分页测试
[TestMethod]
public void ToPagedResult_BasicPaging_ReturnsCorrectPage()
{
// Arrange
var items = Enumerable.Range(1, 100).ToList();
// Act
var page1 = items.ToPagedResult(1, 10);
var page2 = items.ToPagedResult(2, 10);
// Assert
Assert.AreEqual(1, page1.PageIndex);
Assert.AreEqual(10, page1.PageSize);
Assert.AreEqual(100, page1.TotalCount);
Assert.AreEqual(10, page1.TotalPages);
Assert.AreEqual(10, page1.Items.Count);
Assert.AreEqual(1, page1.Items.First());
Assert.AreEqual(10, page1.Items.Last());
Assert.AreEqual(11, page2.Items.First());
Assert.AreEqual(20, page2.Items.Last());
}
[TestMethod]
public void ToPagedResult_LastPage_ReturnsPartialPage()
{
// Arrange
var items = Enumerable.Range(1, 25).ToList();
// Act
var lastPage = items.ToPagedResult(3, 10);
// Assert
Assert.AreEqual(3, lastPage.PageIndex);
Assert.AreEqual(5, lastPage.Items.Count); // 最后一页只有 5 个元素
Assert.AreEqual(21, lastPage.Items.First());
Assert.AreEqual(25, lastPage.Items.Last());
}
[TestMethod]
public void ToPagedResult_InvalidPageIndex_ClampsToValidRange()
{
// Arrange
var items = Enumerable.Range(1, 50).ToList();
// Act
var zeroPage = items.ToPagedResult(0, 10); // 应该被修正为第 1 页
var negativePage = items.ToPagedResult(-1, 10); // 应该被修正为第 1 页
// Assert
Assert.AreEqual(1, zeroPage.PageIndex);
Assert.AreEqual(1, negativePage.PageIndex);
}
[TestMethod]
public void PagedResult_Navigation_PropertiesWorkCorrectly()
{
// Arrange
var items = Enumerable.Range(1, 50).ToList();
// Act
var firstPage = items.ToPagedResult(1, 10);
var middlePage = items.ToPagedResult(3, 10);
var lastPage = items.ToPagedResult(5, 10);
// Assert
Assert.IsFalse(firstPage.HasPreviousPage);
Assert.IsTrue(firstPage.HasNextPage);
Assert.IsTrue(middlePage.HasPreviousPage);
Assert.IsTrue(middlePage.HasNextPage);
Assert.IsTrue(lastPage.HasPreviousPage);
Assert.IsFalse(lastPage.HasNextPage);
}
#endregion
#region 树形结构测试
[TestMethod]
public void ToTree_FlatListToTree_BuildsCorrectHierarchy()
{
// Arrange: 创建平铺的列表
var items = new List<TestItem>
{
new() { Id = 1, Name = "根节点1", ParentId = null },
new() { Id = 2, Name = "根节点2", ParentId = null },
new() { Id = 3, Name = "子节点1-1", ParentId = 1 },
new() { Id = 4, Name = "子节点1-2", ParentId = 1 },
new() { Id = 5, Name = "子节点2-1", ParentId = 2 },
new() { Id = 6, Name = "孙节点1-1-1", ParentId = 3 }
};
// Act
var tree = items.ToTree(
idSelector: x => x.Id,
parentIdSelector: x => x.ParentId,
rootParentId: null
);
// Assert
Assert.AreEqual(2, tree.Count); // 两个根节点
Assert.AreEqual("根节点1", tree[0].Data.Name);
Assert.AreEqual(2, tree[0].Children.Count); // 根节点1 有两个子节点
Assert.AreEqual("子节点1-1", tree[0].Children[0].Data.Name);
Assert.AreEqual(1, tree[0].Children[0].Children.Count); // 子节点1-1 有一个孙节点
Assert.AreEqual("孙节点1-1-1", tree[0].Children[0].Children[0].Data.Name);
}
[TestMethod]
public void ToTree_BuildsCorrectLevels()
{
// Arrange
var items = new List<TestItem>
{
new() { Id = 1, Name = "根", ParentId = null },
new() { Id = 2, Name = "子", ParentId = 1 },
new() { Id = 3, Name = "孙", ParentId = 2 }
};
// Act
var tree = items.ToTree(x => x.Id, x => x.ParentId);
// Assert
Assert.AreEqual(0, tree[0].Level); // 根节点 Level = 0
Assert.AreEqual(1, tree[0].Children[0].Level); // 子节点 Level = 1
Assert.AreEqual(2, tree[0].Children[0].Children[0].Level); // 孙节点 Level = 2
}
[TestMethod]
public void ToFlatList_TreeToFlatList_PreservesAllNodes()
{
// Arrange
var items = new List<TestItem>
{
new() { Id = 1, Name = "根", ParentId = null },
new() { Id = 2, Name = "子1", ParentId = 1 },
new() { Id = 3, Name = "子2", ParentId = 1 },
new() { Id = 4, Name = "孙", ParentId = 2 }
};
var tree = items.ToTree(x => x.Id, x => x.ParentId);
// Act
var flatList = tree.ToFlatList();
// Assert
Assert.AreEqual(4, flatList.Count);
Assert.AreEqual("根", flatList[0].Name);
Assert.AreEqual("子1", flatList[1].Name);
Assert.AreEqual("孙", flatList[2].Name); // 深度优先遍历
Assert.AreEqual("子2", flatList[3].Name);
}
[TestMethod]
public void TraverseTree_ExecutesActionForAllNodes()
{
// Arrange
var items = new List<TestItem>
{
new() { Id = 1, Name = "A", ParentId = null },
new() { Id = 2, Name = "B", ParentId = 1 },
new() { Id = 3, Name = "C", ParentId = 1 }
};
var tree = items.ToTree(x => x.Id, x => x.ParentId);
var visitedNames = new List<string>();
// Act
tree.TraverseTree(node => visitedNames.Add(node.Data.Name));
// Assert
Assert.AreEqual(3, visitedNames.Count);
CollectionAssert.Contains(visitedNames, "A");
CollectionAssert.Contains(visitedNames, "B");
CollectionAssert.Contains(visitedNames, "C");
}
#endregion
#region 批处理测试
[TestMethod]
public void Batch_DividesIntoCorrectBatches()
{
// Arrange
var items = Enumerable.Range(1, 10).ToList();
// Act
var batches = items.Batch(3).ToList();
// Assert
Assert.AreEqual(4, batches.Count); // 10 个元素,每批 3 个,共 4 批
Assert.AreEqual(3, batches[0].Count());
Assert.AreEqual(3, batches[1].Count());
Assert.AreEqual(3, batches[2].Count());
Assert.AreEqual(1, batches[3].Count()); // 最后一批只有 1 个
}
[TestMethod]
public void Batch_EmptyCollection_ReturnsEmpty()
{
// Arrange
var items = new List<int>();
// Act
var batches = items.Batch(5).ToList();
// Assert
Assert.AreEqual(0, batches.Count);
}
[TestMethod]
public void ForEachBatch_ExecutesActionForEachBatch()
{
// Arrange
var items = Enumerable.Range(1, 25).ToList();
var processedBatches = new List<int>();
// Act
items.ForEachBatch(10, batch =>
{
processedBatches.Add(batch.Count());
});
// Assert
Assert.AreEqual(3, processedBatches.Count);
Assert.AreEqual(10, processedBatches[0]);
Assert.AreEqual(10, processedBatches[1]);
Assert.AreEqual(5, processedBatches[2]);
}
#endregion
#region 空集合安全操作测试
[TestMethod]
public void OrEmpty_NullCollection_ReturnsEmptyCollection()
{
// Arrange
List<int>? nullList = null;
// Act
var result = nullList.OrEmpty();
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(0, result.Count());
}
[TestMethod]
public void OrDefault_EmptyCollection_ReturnsDefaultValue()
{
// Arrange
var emptyList = new List<int>();
var defaultList = new List<int> { 1, 2, 3 };
// Act
var result = emptyList.OrDefault(defaultList);
// Assert
Assert.AreEqual(3, result.Count());
CollectionAssert.AreEqual(defaultList, result.ToList());
}
[TestMethod]
public void IsNullOrEmpty_VariousInputs_ReturnsCorrectResult()
{
// Arrange
List<int>? nullList = null;
var emptyList = new List<int>();
var nonEmptyList = new List<int> { 1 };
// Act & Assert
Assert.IsTrue(nullList.IsNullOrEmpty());
Assert.IsTrue(emptyList.IsNullOrEmpty());
Assert.IsFalse(nonEmptyList.IsNullOrEmpty());
}
[TestMethod]
public void HasItems_VariousInputs_ReturnsCorrectResult()
{
// Arrange
List<int>? nullList = null;
var emptyList = new List<int>();
var nonEmptyList = new List<int> { 1 };
// Act & Assert
Assert.IsFalse(nullList.HasItems());
Assert.IsFalse(emptyList.HasItems());
Assert.IsTrue(nonEmptyList.HasItems());
}
#endregion
#region DistinctBy 测试
[TestMethod]
public void DistinctBy_RemovesDuplicatesByKey()
{
// Arrange
var items = new List<TestItem>
{
new() { Id = 1, Name = "A" },
new() { Id = 2, Name = "B" },
new() { Id = 3, Name = "A" }, // 重复的 Name
new() { Id = 4, Name = "C" }
};
// Act (.NET 6+ 内置 DistinctBy)
var distinct = items.DistinctBy(x => x.Name).ToList();
// Assert
Assert.AreEqual(3, distinct.Count);
Assert.AreEqual(1, distinct[0].Id); // 保留第一个 "A"
Assert.AreEqual(2, distinct[1].Id);
Assert.AreEqual(4, distinct[2].Id);
}
#endregion
#region 其他实用扩展测试
[TestMethod]
public void ForEach_ExecutesActionForAllElements()
{
// Arrange
var items = new List<int> { 1, 2, 3 };
var sum = 0;
// Act
items.ForEach(x => sum += x);
// Assert
Assert.AreEqual(6, sum);
}
[TestMethod]
public void ForEach_WithIndex_ProvidesCorrectIndex()
{
// Arrange
var items = new List<string> { "A", "B", "C" };
var results = new List<string>();
// Act
items.ForEach((item, index) => results.Add($"{index}:{item}"));
// Assert
CollectionAssert.AreEqual(new[] { "0:A", "1:B", "2:C" }, results);
}
[TestMethod]
public void JoinString_ConcatenatesWithSeparator()
{
// Arrange
var items = new[] { "apple", "banana", "cherry" };
// Act
var result = items.JoinString(", ");
// Assert
Assert.AreEqual("apple, banana, cherry", result);
}
[TestMethod]
public void Shuffle_ChangesOrder()
{
// Arrange
var items = Enumerable.Range(1, 100).ToList();
var original = items.ToList();
// Act
var shuffled = items.Shuffle().ToList();
// Assert: 打乱后的顺序应该不同(理论上有极小概率相同)
Assert.AreEqual(original.Count, shuffled.Count);
// 检查是否至少有一些元素位置变化
var differentPositions = original.Where((item, index) => shuffled[index] != item).Count();
Assert.IsTrue(differentPositions > 10); // 至少 10% 的元素位置不同
}
[TestMethod]
public void TakeRandom_ReturnsSpecifiedCount()
{
// Arrange
var items = Enumerable.Range(1, 100).ToList();
// Act
var random10 = items.TakeRandom(10).ToList();
// Assert
Assert.AreEqual(10, random10.Count);
Assert.IsTrue(random10.All(x => items.Contains(x)));
}
[TestMethod]
public void Split_DividesIntoParts()
{
// Arrange
var items = Enumerable.Range(1, 10).ToList();
// Act
var parts = items.Split(3).ToList();
// Assert
Assert.AreEqual(3, parts.Count);
Assert.AreEqual(4, parts[0].Count()); // 10 / 3 = 向上取整 4
Assert.AreEqual(4, parts[1].Count());
Assert.AreEqual(2, parts[2].Count());
}
[TestMethod]
public void AllUnique_ChecksUniqueness()
{
// Arrange
var uniqueList = new[] { 1, 2, 3, 4 };
var duplicateList = new[] { 1, 2, 2, 3 };
// Act & Assert
Assert.IsTrue(uniqueList.AllUnique());
Assert.IsFalse(duplicateList.AllUnique());
}
[TestMethod]
public void HasDuplicates_DetectsDuplicates()
{
// Arrange
var uniqueList = new[] { 1, 2, 3, 4 };
var duplicateList = new[] { 1, 2, 2, 3 };
// Act & Assert
Assert.IsFalse(uniqueList.HasDuplicates());
Assert.IsTrue(duplicateList.HasDuplicates());
}
[TestMethod]
public void GetDuplicates_ReturnsOnlyDuplicates()
{
// Arrange
var items = new[] { 1, 2, 2, 3, 3, 3, 4 };
// Act
var duplicates = items.GetDuplicates().ToList();
// Assert
Assert.AreEqual(2, duplicates.Count);
CollectionAssert.Contains(duplicates, 2);
CollectionAssert.Contains(duplicates, 3);
CollectionAssert.DoesNotContain(duplicates, 1);
CollectionAssert.DoesNotContain(duplicates, 4);
}
[TestMethod]
public void Interleave_MergesAlternately()
{
// Arrange
var first = new[] { 1, 3, 5 };
var second = new[] { 2, 4, 6 };
// Act
var result = first.Interleave(second).ToList();
// Assert
CollectionAssert.AreEqual(new[] { 1, 2, 3, 4, 5, 6 }, result);
}
[TestMethod]
public void Interleave_DifferentLengths_MergesCorrectly()
{
// Arrange
var first = new[] { 1, 3 };
var second = new[] { 2, 4, 6, 8 };
// Act
var result = first.Interleave(second).ToList();
// Assert
CollectionAssert.AreEqual(new[] { 1, 2, 3, 4, 6, 8 }, result);
}
[TestMethod]
public void WhereNotNull_FiltersNullValues()
{
// Arrange
var items = new List<string?> { "A", null, "B", null, "C" };
// Act
var result = items.WhereNotNull().ToList();
// Assert
Assert.AreEqual(3, result.Count);
CollectionAssert.AreEqual(new[] { "A", "B", "C" }, result);
}
[TestMethod]
public void ToDictionaryList_GroupsCorrectly()
{
// Arrange
var items = new List<TestItem>
{
new() { Id = 1, Name = "A", ParentId = 1 },
new() { Id = 2, Name = "B", ParentId = 1 },
new() { Id = 3, Name = "C", ParentId = 2 },
new() { Id = 4, Name = "D", ParentId = 2 }
};
// Act
var grouped = items.ToDictionaryList(
x => x.ParentId!.Value,
x => x.Name
);
// Assert
Assert.AreEqual(2, grouped.Count);
Assert.AreEqual(2, grouped[1].Count);
CollectionAssert.Contains(grouped[1], "A");
CollectionAssert.Contains(grouped[1], "B");
Assert.AreEqual(2, grouped[2].Count);
CollectionAssert.Contains(grouped[2], "C");
CollectionAssert.Contains(grouped[2], "D");
}
#endregion
#region 实际应用场景测试
[TestMethod]
public void Scenario_PaginationWithSearch()
{
// Arrange: 模拟产品列表搜索和分页
var products = Enumerable.Range(1, 100)
.Select(i => new { Id = i, Name = $"Product {i}", Price = i * 10 })
.ToList();
// Act: 搜索价格大于 500 的产品,并分页
var searchResults = products
.Where(p => p.Price > 500)
.ToPagedResult(1, 10);
// Assert
Assert.AreEqual(10, searchResults.Items.Count);
Assert.IsTrue(searchResults.Items.All(p => p.Price > 500));
Assert.IsTrue(searchResults.TotalCount > 40); // 总共有 50+ 个符合条件的产品
}
[TestMethod]
public void Scenario_OrganizationTree()
{
// Arrange: 模拟组织架构树
var departments = new List<TestItem>
{
new() { Id = 1, Name = "总公司", ParentId = null },
new() { Id = 2, Name = "技术部", ParentId = 1 },
new() { Id = 3, Name = "市场部", ParentId = 1 },
new() { Id = 4, Name = "前端组", ParentId = 2 },
new() { Id = 5, Name = "后端组", ParentId = 2 },
new() { Id = 6, Name = "运营组", ParentId = 3 }
};
// Act: 构建组织树
var tree = departments.ToTree(x => x.Id, x => x.ParentId);
// Assert: 验证树形结构
Assert.AreEqual(1, tree.Count); // 1 个根节点(总公司)
Assert.AreEqual(2, tree[0].Children.Count); // 2 个一级部门
Assert.AreEqual(2, tree[0].Children[0].Children.Count); // 技术部有 2 个组
Assert.AreEqual("前端组", tree[0].Children[0].Children[0].Data.Name);
}
[TestMethod]
public void Scenario_BatchProcessing()
{
// Arrange: 模拟批量导入数据
var records = Enumerable.Range(1, 1000).ToList();
var processedCount = 0;
// Act: 每批处理 100 条记录
records.ForEachBatch(100, batch =>
{
// 模拟批量插入数据库
processedCount += batch.Count();
});
// Assert
Assert.AreEqual(1000, processedCount);
}
[TestMethod]
public void Scenario_DataCleaning()
{
// Arrange: 模拟清洗数据(去除 null、去重、过滤)
var rawData = new List<string?> { "A", null, "B", "A", null, "C", "B", "D" };
// Act: 数据清洗流水线
var cleanedData = rawData
.WhereNotNull() // 去除 null
.DistinctBy(x => x) // 去重
.Where(x => x != "D") // 过滤不需要的数据
.ToList();
// Assert
Assert.AreEqual(3, cleanedData.Count);
CollectionAssert.AreEqual(new[] { "A", "B", "C" }, cleanedData);
}
#endregion
}
+634
View File
@@ -0,0 +1,634 @@
using System.ComponentModel;
using Common.Utils;
namespace Common.Test;
/// <summary>
/// EnumHelper 枚举工具测试
/// 展示枚举解析、描述获取、标志位操作等功能
/// </summary>
[TestClass]
public class EnumHelperTests
{
#region 测试枚举定义
/// <summary>
/// 订单状态枚举
/// </summary>
public enum OrderStatus
{
[System.ComponentModel.Description("待支付")]
Pending = 0,
[System.ComponentModel.Description("已支付")]
Paid = 1,
[System.ComponentModel.Description("已发货")]
Shipped = 2,
[System.ComponentModel.Description("已完成")]
Completed = 3,
[System.ComponentModel.Description("已取消")]
Cancelled = 4
}
/// <summary>
/// 用户权限枚举(标志位)
/// </summary>
[Flags]
public enum UserPermissions
{
[System.ComponentModel.Description("无权限")]
None = 0,
[System.ComponentModel.Description("读取权限")]
Read = 1,
[System.ComponentModel.Description("写入权限")]
Write = 2,
[System.ComponentModel.Description("删除权限")]
Delete = 4,
[System.ComponentModel.Description("管理权限")]
Admin = 8,
[System.ComponentModel.Description("全部权限")]
All = Read | Write | Delete | Admin
}
/// <summary>
/// 日志级别(无描述)
/// </summary>
public enum LogLevel
{
Debug = 1,
Info = 2,
Warning = 3,
Error = 4,
Fatal = 5
}
#endregion
#region 枚举解析测试
[TestMethod]
public void Parse_ValidString_ReturnsEnum()
{
// Act
var result1 = EnumHelper.Parse<OrderStatus>("Paid");
var result2 = EnumHelper.Parse<OrderStatus>("paid"); // 忽略大小写
// Assert
Assert.IsNotNull(result1);
Assert.AreEqual(OrderStatus.Paid, result1.Value);
Assert.IsNotNull(result2);
Assert.AreEqual(OrderStatus.Paid, result2.Value);
}
[TestMethod]
public void Parse_InvalidString_ReturnsNull()
{
// Act
var result = EnumHelper.Parse<OrderStatus>("InvalidValue");
// Assert
Assert.IsNull(result);
}
[TestMethod]
public void ParseOrDefault_InvalidString_ReturnsDefaultValue()
{
// Act
var result = EnumHelper.ParseOrDefault("InvalidValue", OrderStatus.Pending);
// Assert
Assert.AreEqual(OrderStatus.Pending, result);
}
[TestMethod]
public void ParseFromInt_ValidValue_ReturnsEnum()
{
// Act
var result = EnumHelper.ParseFromInt<OrderStatus>(2);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(OrderStatus.Shipped, result.Value);
}
[TestMethod]
public void ParseFromInt_InvalidValue_ReturnsNull()
{
// Act
var result = EnumHelper.ParseFromInt<OrderStatus>(999);
// Assert
Assert.IsNull(result);
}
[TestMethod]
public void ParseFromDescription_ValidDescription_ReturnsEnum()
{
// Act
var result = EnumHelper.ParseFromDescription<OrderStatus>("已支付");
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(OrderStatus.Paid, result.Value);
}
[TestMethod]
public void ParseFromDescription_InvalidDescription_ReturnsNull()
{
// Act
var result = EnumHelper.ParseFromDescription<OrderStatus>("不存在的状态");
// Assert
Assert.IsNull(result);
}
#endregion
#region 枚举描述测试
[TestMethod]
public void GetDescription_WithDescriptionAttribute_ReturnsDescription()
{
// Arrange
var status = OrderStatus.Paid;
// Act
var description = status.GetDescription();
// Assert
Assert.AreEqual("已支付", description);
}
[TestMethod]
public void GetDescription_WithoutDescriptionAttribute_ReturnsEnumName()
{
// Arrange
var level = LogLevel.Error;
// Act
var description = level.GetDescription();
// Assert
Assert.AreEqual("Error", description);
}
[TestMethod]
public void GetAllDescriptions_ReturnsAllDescriptions()
{
// Act
var descriptions = EnumHelper.GetAllDescriptions<OrderStatus>();
// Assert
Assert.AreEqual(5, descriptions.Count);
Assert.AreEqual("待支付", descriptions[OrderStatus.Pending]);
Assert.AreEqual("已支付", descriptions[OrderStatus.Paid]);
Assert.AreEqual("已完成", descriptions[OrderStatus.Completed]);
}
#endregion
#region 枚举列表测试
[TestMethod]
public void GetValues_ReturnsAllValues()
{
// Act
var values = EnumHelper.GetValues<OrderStatus>();
// Assert
Assert.AreEqual(5, values.Length);
CollectionAssert.Contains(values, OrderStatus.Pending);
CollectionAssert.Contains(values, OrderStatus.Paid);
CollectionAssert.Contains(values, OrderStatus.Shipped);
}
[TestMethod]
public void GetNames_ReturnsAllNames()
{
// Act
var names = EnumHelper.GetNames<OrderStatus>();
// Assert
Assert.AreEqual(5, names.Length);
CollectionAssert.Contains(names, "Pending");
CollectionAssert.Contains(names, "Paid");
CollectionAssert.Contains(names, "Shipped");
}
[TestMethod]
public void GetOptions_ReturnsListForDropdown()
{
// Act
var options = EnumHelper.GetOptions<OrderStatus>();
// Assert
Assert.AreEqual(5, options.Count);
var paidOption = options.First(o => o.Value == 1);
Assert.AreEqual("Paid", paidOption.Name);
Assert.AreEqual("已支付", paidOption.Description);
Assert.AreEqual("已支付", paidOption.DisplayText);
}
[TestMethod]
public void GetDictionary_ReturnsValueNamePairs()
{
// Act
var dict = EnumHelper.GetDictionary<OrderStatus>();
// Assert
Assert.AreEqual(5, dict.Count);
Assert.AreEqual("Paid", dict[1]);
Assert.AreEqual("Shipped", dict[2]);
}
[TestMethod]
public void GetDictionaryWithDescription_ReturnsValueDescriptionPairs()
{
// Act
var dict = EnumHelper.GetDictionaryWithDescription<OrderStatus>();
// Assert
Assert.AreEqual(5, dict.Count);
Assert.AreEqual("已支付", dict[1]);
Assert.AreEqual("已发货", dict[2]);
}
#endregion
#region 枚举验证测试
[TestMethod]
public void IsDefined_ValidValue_ReturnsTrue()
{
// Act & Assert
Assert.IsTrue(EnumHelper.IsDefined<OrderStatus>(1));
Assert.IsTrue(EnumHelper.IsDefined<OrderStatus>("Paid"));
Assert.IsTrue(EnumHelper.IsDefined(OrderStatus.Paid));
}
[TestMethod]
public void IsDefined_InvalidValue_ReturnsFalse()
{
// Act & Assert
Assert.IsFalse(EnumHelper.IsDefined<OrderStatus>(999));
Assert.IsFalse(EnumHelper.IsDefined<OrderStatus>("InvalidStatus"));
}
#endregion
#region 标志位枚举操作测试
[TestMethod]
public void HasFlag_ChecksFlagCorrectly()
{
// Arrange
var permissions = UserPermissions.Read | UserPermissions.Write;
// Act & Assert
Assert.IsTrue(permissions.HasFlag(UserPermissions.Read));
Assert.IsTrue(permissions.HasFlag(UserPermissions.Write));
Assert.IsFalse(permissions.HasFlag(UserPermissions.Delete));
}
[TestMethod]
public void AddFlag_AddsNewFlag()
{
// Arrange
var permissions = UserPermissions.Read;
// Act
var newPermissions = permissions.AddFlag(UserPermissions.Write);
// Assert
Assert.IsTrue(newPermissions.HasFlag(UserPermissions.Read));
Assert.IsTrue(newPermissions.HasFlag(UserPermissions.Write));
}
[TestMethod]
public void RemoveFlag_RemovesExistingFlag()
{
// Arrange
var permissions = UserPermissions.Read | UserPermissions.Write | UserPermissions.Delete;
// Act
var newPermissions = permissions.RemoveFlag(UserPermissions.Write);
// Assert
Assert.IsTrue(newPermissions.HasFlag(UserPermissions.Read));
Assert.IsFalse(newPermissions.HasFlag(UserPermissions.Write));
Assert.IsTrue(newPermissions.HasFlag(UserPermissions.Delete));
}
[TestMethod]
public void ToggleFlag_TogglesFlag()
{
// Arrange
var permissions = UserPermissions.Read;
// Act: 切换 Write(添加)
var withWrite = permissions.ToggleFlag(UserPermissions.Write);
Assert.IsTrue(withWrite.HasFlag(UserPermissions.Write));
// Act: 再次切换 Write(移除)
var withoutWrite = withWrite.ToggleFlag(UserPermissions.Write);
Assert.IsFalse(withoutWrite.HasFlag(UserPermissions.Write));
}
[TestMethod]
public void GetFlags_ReturnsAllSetFlags()
{
// Arrange
var permissions = UserPermissions.Read | UserPermissions.Write | UserPermissions.Admin;
// Act
var flags = permissions.GetFlags().ToList();
// Assert: None 不应该包含在内(因为值是 0)
Assert.IsTrue(flags.Contains(UserPermissions.Read));
Assert.IsTrue(flags.Contains(UserPermissions.Write));
Assert.IsTrue(flags.Contains(UserPermissions.Admin));
Assert.IsFalse(flags.Contains(UserPermissions.Delete));
}
[TestMethod]
public void CombineFlags_CombinesMultipleFlags()
{
// Act
var combined = EnumHelper.CombineFlags(
UserPermissions.Read,
UserPermissions.Write,
UserPermissions.Delete
);
// Assert
Assert.IsTrue(combined.HasFlag(UserPermissions.Read));
Assert.IsTrue(combined.HasFlag(UserPermissions.Write));
Assert.IsTrue(combined.HasFlag(UserPermissions.Delete));
Assert.IsFalse(combined.HasFlag(UserPermissions.Admin));
}
#endregion
#region 枚举转换测试
[TestMethod]
public void ToInt_ConvertsToInteger()
{
// Arrange
var status = OrderStatus.Paid;
// Act
var intValue = status.ToInt();
// Assert
Assert.AreEqual(1, intValue);
}
[TestMethod]
public void ToLong_ConvertsToLong()
{
// Arrange
var status = OrderStatus.Shipped;
// Act
var longValue = status.ToLong();
// Assert
Assert.AreEqual(2L, longValue);
}
[TestMethod]
public void ToEnum_ConvertsIntToEnum()
{
// Arrange
int value = 3;
// Act
var status = value.ToEnum<OrderStatus>();
// Assert
Assert.AreEqual(OrderStatus.Completed, status);
}
#endregion
#region 枚举信息测试
[TestMethod]
public void GetCount_ReturnsEnumCount()
{
// Act
var count = EnumHelper.GetCount<OrderStatus>();
// Assert
Assert.AreEqual(5, count);
}
[TestMethod]
public void GetMinValue_ReturnsSmallestValue()
{
// Act
var min = EnumHelper.GetMinValue<OrderStatus>();
// Assert
Assert.AreEqual(OrderStatus.Pending, min);
}
[TestMethod]
public void GetMaxValue_ReturnsLargestValue()
{
// Act
var max = EnumHelper.GetMaxValue<OrderStatus>();
// Assert
Assert.AreEqual(OrderStatus.Cancelled, max);
}
[TestMethod]
public void IsFlagsEnum_DetectsFlagsAttribute()
{
// Act
var isFlagsEnum = EnumHelper.IsFlagsEnum<UserPermissions>();
var isNotFlagsEnum = EnumHelper.IsFlagsEnum<OrderStatus>();
// Assert
Assert.IsTrue(isFlagsEnum);
Assert.IsFalse(isNotFlagsEnum);
}
#endregion
#region 枚举比较测试
[TestMethod]
public void Equals_ComparesEnumValues()
{
// Act & Assert
Assert.IsTrue(EnumHelper.Equals(OrderStatus.Paid, OrderStatus.Paid));
Assert.IsFalse(EnumHelper.Equals(OrderStatus.Paid, OrderStatus.Pending));
}
[TestMethod]
public void In_ChecksIfValueInList()
{
// Arrange
var status = OrderStatus.Paid;
// Act & Assert
Assert.IsTrue(status.In(OrderStatus.Pending, OrderStatus.Paid, OrderStatus.Shipped));
Assert.IsFalse(status.In(OrderStatus.Completed, OrderStatus.Cancelled));
}
[TestMethod]
public void NotIn_ChecksIfValueNotInList()
{
// Arrange
var status = OrderStatus.Paid;
// Act & Assert
Assert.IsFalse(status.NotIn(OrderStatus.Pending, OrderStatus.Paid, OrderStatus.Shipped));
Assert.IsTrue(status.NotIn(OrderStatus.Completed, OrderStatus.Cancelled));
}
#endregion
#region 随机枚举测试
[TestMethod]
public void GetRandom_ReturnsValidEnum()
{
// Act
var random = EnumHelper.GetRandom<OrderStatus>();
// Assert
Assert.IsTrue(EnumHelper.IsDefined(random));
}
[TestMethod]
public void GetRandomExcept_ExcludesSpecifiedValues()
{
// Act: 多次获取随机值,确保不包含排除的值
for (int i = 0; i < 10; i++)
{
var random = EnumHelper.GetRandomExcept(OrderStatus.Pending, OrderStatus.Cancelled);
// Assert
Assert.IsTrue(random.NotIn(OrderStatus.Pending, OrderStatus.Cancelled));
}
}
#endregion
#region 实际应用场景测试
[TestMethod]
public void Scenario_OrderStatusWorkflow()
{
// Arrange: 模拟订单状态流转
var currentStatus = OrderStatus.Pending;
// Act: 支付订单
currentStatus = OrderStatus.Paid;
Assert.AreEqual("已支付", currentStatus.GetDescription());
// Act: 发货
currentStatus = OrderStatus.Shipped;
Assert.AreEqual("已发货", currentStatus.GetDescription());
// Assert: 检查状态是否在允许的范围内
var validStatuses = new[] { OrderStatus.Shipped, OrderStatus.Completed };
Assert.IsTrue(currentStatus.In(validStatuses));
}
[TestMethod]
public void Scenario_PermissionManagement()
{
// Arrange: 初始化普通用户权限
var userPermissions = UserPermissions.Read;
// Act: 升级为编辑权限
userPermissions = userPermissions.AddFlag(UserPermissions.Write);
Assert.IsTrue(userPermissions.HasFlag(UserPermissions.Write));
// Act: 再添加删除权限
userPermissions = userPermissions.AddFlag(UserPermissions.Delete);
// Assert: 验证权限
var grantedPermissions = userPermissions.GetFlags().ToList();
Assert.AreEqual(3, grantedPermissions.Count);
Assert.IsTrue(grantedPermissions.Contains(UserPermissions.Read));
Assert.IsTrue(grantedPermissions.Contains(UserPermissions.Write));
Assert.IsTrue(grantedPermissions.Contains(UserPermissions.Delete));
// Act: 撤销写入权限
userPermissions = userPermissions.RemoveFlag(UserPermissions.Write);
Assert.IsFalse(userPermissions.HasFlag(UserPermissions.Write));
}
[TestMethod]
public void Scenario_DropdownBinding()
{
// Arrange: 模拟为前端下拉框准备数据
var statusOptions = EnumHelper.GetOptions<OrderStatus>();
// Act: 转换为前端所需的格式
var dropdownData = statusOptions.Select(o => new
{
Value = o.Value,
Text = o.DisplayText
}).ToList();
// Assert
Assert.AreEqual(5, dropdownData.Count);
Assert.AreEqual("待支付", dropdownData[0].Text);
Assert.AreEqual(0, dropdownData[0].Value);
}
[TestMethod]
public void Scenario_StatusValidation()
{
// Arrange: 从前端接收状态值
var statusFromFrontend = 2;
// Act: 验证并转换
if (EnumHelper.IsDefined<OrderStatus>(statusFromFrontend))
{
var status = statusFromFrontend.ToEnum<OrderStatus>();
var description = status.GetDescription();
// Assert
Assert.AreEqual(OrderStatus.Shipped, status);
Assert.AreEqual("已发货", description);
}
else
{
Assert.Fail("Invalid status value");
}
}
[TestMethod]
public void Scenario_ParseUserInput()
{
// Arrange: 用户输入的状态名称
var userInput = "paid"; // 可能是小写
// Act: 解析
var status = EnumHelper.Parse<OrderStatus>(userInput);
// Assert
Assert.IsNotNull(status);
Assert.AreEqual(OrderStatus.Paid, status.Value);
Assert.AreEqual("已支付", status.Value.GetDescription());
}
#endregion
}
+674
View File
@@ -0,0 +1,674 @@
using System.ComponentModel;
using System.Reflection;
using Common.Utils;
namespace Common.Test;
/// <summary>
/// ReflectionHelper 反射工具测试
/// 展示类型扫描、属性访问、特性读取等功能
/// </summary>
[TestClass]
public class ReflectionHelperTests
{
#region 测试类定义
/// <summary>
/// 测试基类
/// </summary>
public abstract class BaseEntity
{
public int Id { get; set; }
}
/// <summary>
/// 测试接口
/// </summary>
public interface ITestService
{
void Execute();
}
/// <summary>
/// 测试特性
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class TestAttribute : Attribute
{
public string Name { get; set; }
public TestAttribute(string name)
{
Name = name;
}
}
/// <summary>
/// 测试实体类
/// </summary>
[Test("UserEntity")]
public class User : BaseEntity
{
[Test("UserName")]
[System.ComponentModel.Description("用户名")]
public string Name { get; set; } = "";
[System.ComponentModel.Description("用户年龄")]
public int Age { get; set; }
public string Email { get; set; } = "";
public DateTime CreatedAt { get; set; } = DateTime.Now;
public void SayHello()
{
Console.WriteLine($"Hello, I'm {Name}");
}
public static string GetVersion()
{
return "1.0.0";
}
public int Calculate(int a, int b)
{
return a + b;
}
}
/// <summary>
/// 测试 DTO
/// </summary>
public class UserDto
{
public string Name { get; set; } = "";
public int Age { get; set; }
public string Email { get; set; } = "";
}
/// <summary>
/// 测试服务实现
/// </summary>
public class TestService : ITestService
{
public void Execute()
{
Console.WriteLine("Executing test service");
}
}
#endregion
#region 类型扫描测试
[TestMethod]
public void FindSubclassesOf_FindsAllSubclasses()
{
// Act
var subclasses = ReflectionHelper.FindSubclassesOf<BaseEntity>();
// Assert
Assert.IsTrue(subclasses.Count > 0);
Assert.IsTrue(subclasses.Any(t => t == typeof(User)));
}
[TestMethod]
public void FindImplementationsOf_FindsAllImplementations()
{
// Arrange
var assembly = Assembly.GetExecutingAssembly();
// Act
var implementations = ReflectionHelper.FindImplementationsOf<ITestService>(assembly);
// Assert
Assert.IsTrue(implementations.Count > 0);
Assert.IsTrue(implementations.Any(t => t == typeof(TestService)));
}
[TestMethod]
public void FindTypesWithAttribute_FindsTypesWithAttribute()
{
// Arrange
var assembly = Assembly.GetExecutingAssembly();
// Act
var types = ReflectionHelper.FindTypesWithAttribute<TestAttribute>(assembly);
// Assert
Assert.IsTrue(types.Count > 0);
Assert.IsTrue(types.Any(t => t == typeof(User)));
}
#endregion
#region 属性访问测试
[TestMethod]
public void GetPropertyValue_ReturnsCorrectValue()
{
// Arrange
var user = new User { Name = "Alice", Age = 25 };
// Act
var name = ReflectionHelper.GetPropertyValue(user, nameof(User.Name));
var age = ReflectionHelper.GetPropertyValue(user, nameof(User.Age));
// Assert
Assert.AreEqual("Alice", name);
Assert.AreEqual(25, age);
}
[TestMethod]
public void SetPropertyValue_SetsValueCorrectly()
{
// Arrange
var user = new User();
// Act
ReflectionHelper.SetPropertyValue(user, nameof(User.Name), "Bob");
ReflectionHelper.SetPropertyValue(user, nameof(User.Age), 30);
// Assert
Assert.AreEqual("Bob", user.Name);
Assert.AreEqual(30, user.Age);
}
[TestMethod]
public void GetPropertyValue_Performance_IsFasterThanDirectReflection()
{
// Arrange
var user = new User { Name = "Alice", Age = 25 };
const int iterations = 10000;
// 预热缓存
ReflectionHelper.GetPropertyValue(user, nameof(User.Name));
// Act: 使用 ReflectionHelper(有缓存)
var sw1 = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
_ = ReflectionHelper.GetPropertyValue(user, nameof(User.Name));
}
sw1.Stop();
// Act: 使用原生反射(无缓存)
var propertyInfo = typeof(User).GetProperty(nameof(User.Name))!;
var sw2 = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
_ = propertyInfo.GetValue(user);
}
sw2.Stop();
// Assert: ReflectionHelper 应该比直接反射快(由于缓存和表达式树)
Console.WriteLine($"ReflectionHelper: {sw1.ElapsedMilliseconds}ms");
Console.WriteLine($"Direct Reflection: {sw2.ElapsedMilliseconds}ms");
// 注意:首次运行可能因为 JIT 编译而不准确,多次运行后 ReflectionHelper 应该更快
}
[TestMethod]
public void GetPropertyNames_ReturnsAllPropertyNames()
{
// Act
var propertyNames = ReflectionHelper.GetPropertyNames<User>();
// Assert
Assert.IsTrue(propertyNames.Count >= 5);
CollectionAssert.Contains(propertyNames, nameof(User.Name));
CollectionAssert.Contains(propertyNames, nameof(User.Age));
CollectionAssert.Contains(propertyNames, nameof(User.Email));
}
[TestMethod]
public void GetProperties_ReturnsAllProperties()
{
// Act
var properties = ReflectionHelper.GetProperties<User>();
// Assert
Assert.IsTrue(properties.Length >= 5);
Assert.IsTrue(properties.Any(p => p.Name == nameof(User.Name)));
}
#endregion
#region 特性读取测试
[TestMethod]
public void GetAttribute_ReturnsAttribute()
{
// Act
var attribute = ReflectionHelper.GetAttribute<TestAttribute>(typeof(User));
// Assert
Assert.IsNotNull(attribute);
Assert.AreEqual("UserEntity", attribute.Name);
}
[TestMethod]
public void GetAttribute_FromProperty_ReturnsAttribute()
{
// Arrange
var property = typeof(User).GetProperty(nameof(User.Name))!;
// Act
var testAttr = ReflectionHelper.GetAttribute<TestAttribute>(property);
var descAttr = ReflectionHelper.GetAttribute<System.ComponentModel.DescriptionAttribute>(property);
// Assert
Assert.IsNotNull(testAttr);
Assert.AreEqual("UserName", testAttr.Name);
Assert.IsNotNull(descAttr);
Assert.AreEqual("用户名", descAttr.Description);
}
[TestMethod]
public void HasAttribute_ChecksAttributeExistence()
{
// Act & Assert
Assert.IsTrue(ReflectionHelper.HasAttribute<TestAttribute>(typeof(User)));
Assert.IsFalse(ReflectionHelper.HasAttribute<TestAttribute>(typeof(UserDto)));
}
[TestMethod]
public void GetAttribute_UsesCaching()
{
// Arrange
var type = typeof(User);
// Act: 多次获取应该使用缓存
var attr1 = ReflectionHelper.GetAttribute<TestAttribute>(type);
var attr2 = ReflectionHelper.GetAttribute<TestAttribute>(type);
// Assert: 应该返回相同的实例(来自缓存)
Assert.IsNotNull(attr1);
Assert.IsNotNull(attr2);
}
#endregion
#region 创建实例测试
[TestMethod]
public void CreateInstance_Generic_CreatesInstance()
{
// Act
var user = ReflectionHelper.CreateInstance<User>();
// Assert
Assert.IsNotNull(user);
Assert.IsInstanceOfType(user, typeof(User));
}
[TestMethod]
public void CreateInstance_ByType_CreatesInstance()
{
// Act
var user = ReflectionHelper.CreateInstance(typeof(User));
// Assert
Assert.IsNotNull(user);
Assert.IsInstanceOfType(user, typeof(User));
}
[TestMethod]
public void TryCreateInstance_SuccessfulCreation_ReturnsTrue()
{
// Act
var success = ReflectionHelper.TryCreateInstance<User>(out var user);
// Assert
Assert.IsTrue(success);
Assert.IsNotNull(user);
}
#endregion
#region 属性复制测试
[TestMethod]
public void CopyProperties_CopiesSameNameProperties()
{
// Arrange
var source = new User
{
Name = "Alice",
Age = 25,
Email = "alice@example.com"
};
var target = new UserDto();
// Act
ReflectionHelper.CopyProperties(source, target);
// Assert
Assert.AreEqual("Alice", target.Name);
Assert.AreEqual(25, target.Age);
Assert.AreEqual("alice@example.com", target.Email);
}
[TestMethod]
public void MapTo_CreatesNewInstanceAndCopiesProperties()
{
// Arrange
var source = new User
{
Name = "Bob",
Age = 30,
Email = "bob@example.com"
};
// Act
var dto = ReflectionHelper.MapTo<User, UserDto>(source);
// Assert
Assert.IsNotNull(dto);
Assert.AreEqual("Bob", dto.Name);
Assert.AreEqual(30, dto.Age);
Assert.AreEqual("bob@example.com", dto.Email);
}
[TestMethod]
public void CopyProperties_IgnoreCase_CopiesCorrectly()
{
// Arrange
var source = new { name = "Alice", AGE = 25 };
var target = new UserDto();
// Act
ReflectionHelper.CopyProperties(source, target, ignoreCase: true);
// Assert
Assert.AreEqual("Alice", target.Name);
Assert.AreEqual(25, target.Age);
}
#endregion
#region 方法调用测试
[TestMethod]
public void InvokeMethod_CallsInstanceMethod()
{
// Arrange
var user = new User { Name = "Alice" };
// Act
var result = ReflectionHelper.InvokeMethod(user, nameof(User.Calculate), 10, 20);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(30, result);
}
[TestMethod]
public void InvokeStaticMethod_CallsStaticMethod()
{
// Act
var result = ReflectionHelper.InvokeStaticMethod(typeof(User), nameof(User.GetVersion));
// Assert
Assert.IsNotNull(result);
Assert.AreEqual("1.0.0", result);
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void InvokeMethod_NonExistentMethod_ThrowsException()
{
// Arrange
var user = new User();
// Act
ReflectionHelper.InvokeMethod(user, "NonExistentMethod");
}
#endregion
#region 类型判断测试
[TestMethod]
public void IsNullableType_DetectsNullableTypes()
{
// Act & Assert
Assert.IsTrue(ReflectionHelper.IsNullableType(typeof(int?)));
Assert.IsFalse(ReflectionHelper.IsNullableType(typeof(int)));
Assert.IsFalse(ReflectionHelper.IsNullableType(typeof(string)));
}
[TestMethod]
public void GetUnderlyingType_ReturnsCorrectType()
{
// Act
var underlyingType = ReflectionHelper.GetUnderlyingType(typeof(int?));
// Assert
Assert.AreEqual(typeof(int), underlyingType);
}
[TestMethod]
public void IsValueType_DistinguishesValueTypes()
{
// Act & Assert
Assert.IsTrue(ReflectionHelper.IsValueType(typeof(int)));
Assert.IsTrue(ReflectionHelper.IsValueType(typeof(DateTime)));
Assert.IsFalse(ReflectionHelper.IsValueType(typeof(string)));
Assert.IsFalse(ReflectionHelper.IsValueType(typeof(User)));
}
[TestMethod]
public void IsNumericType_DetectsNumericTypes()
{
// Act & Assert
Assert.IsTrue(ReflectionHelper.IsNumericType(typeof(int)));
Assert.IsTrue(ReflectionHelper.IsNumericType(typeof(double)));
Assert.IsTrue(ReflectionHelper.IsNumericType(typeof(decimal)));
Assert.IsTrue(ReflectionHelper.IsNumericType(typeof(int?)));
Assert.IsFalse(ReflectionHelper.IsNumericType(typeof(string)));
Assert.IsFalse(ReflectionHelper.IsNumericType(typeof(DateTime)));
}
[TestMethod]
public void IsCollectionType_DetectsCollections()
{
// Act & Assert
Assert.IsTrue(ReflectionHelper.IsCollectionType(typeof(int[])));
Assert.IsTrue(ReflectionHelper.IsCollectionType(typeof(List<int>)));
Assert.IsTrue(ReflectionHelper.IsCollectionType(typeof(IEnumerable<int>)));
Assert.IsFalse(ReflectionHelper.IsCollectionType(typeof(int)));
Assert.IsFalse(ReflectionHelper.IsCollectionType(typeof(string)));
}
#endregion
#region 泛型操作测试
[TestMethod]
public void IsGenericType_DetectsGenericTypes()
{
// Act & Assert
Assert.IsTrue(ReflectionHelper.IsGenericType(typeof(List<int>)));
Assert.IsTrue(ReflectionHelper.IsGenericType(typeof(Dictionary<string, int>)));
Assert.IsFalse(ReflectionHelper.IsGenericType(typeof(int)));
Assert.IsFalse(ReflectionHelper.IsGenericType(typeof(string)));
}
[TestMethod]
public void GetGenericArguments_ReturnsTypeArguments()
{
// Act
var args = ReflectionHelper.GetGenericArguments(typeof(Dictionary<string, int>));
// Assert
Assert.AreEqual(2, args.Length);
Assert.AreEqual(typeof(string), args[0]);
Assert.AreEqual(typeof(int), args[1]);
}
[TestMethod]
public void MakeGenericType_ConstructsGenericType()
{
// Act
var listType = ReflectionHelper.MakeGenericType(typeof(List<>), typeof(string));
// Assert
Assert.AreEqual(typeof(List<string>), listType);
}
#endregion
#region 缓存管理测试
[TestMethod]
public void ClearCache_ClearsAllCaches()
{
// Arrange: 先访问一些缓存
ReflectionHelper.GetPropertyValue(new User { Name = "Test" }, nameof(User.Name));
ReflectionHelper.GetAttribute<TestAttribute>(typeof(User));
// Act
ReflectionHelper.ClearCache();
// Assert: 缓存应该被清空(无法直接验证,但不应抛异常)
Assert.IsTrue(true);
}
[TestMethod]
public void ClearPropertyAccessorCache_ClearsPropertyCache()
{
// Arrange
ReflectionHelper.GetPropertyValue(new User { Name = "Test" }, nameof(User.Name));
// Act
ReflectionHelper.ClearPropertyAccessorCache();
// Assert
Assert.IsTrue(true);
}
#endregion
#region 实际应用场景测试
[TestMethod]
public void Scenario_PluginScanning()
{
// Arrange: 模拟插件系统,扫描所有实现 ITestService 的类
var assembly = Assembly.GetExecutingAssembly();
// Act: 查找所有插件
var plugins = ReflectionHelper.FindImplementationsOf<ITestService>(assembly);
// Assert
Assert.IsTrue(plugins.Count > 0);
// Act: 实例化并执行插件
foreach (var pluginType in plugins)
{
if (ReflectionHelper.CreateInstance(pluginType) is ITestService plugin)
{
plugin.Execute(); // 输出:Executing test service
}
}
}
[TestMethod]
public void Scenario_AutoMapper()
{
// Arrange: 模拟 DTO 映射
var user = new User
{
Id = 1,
Name = "Alice",
Age = 25,
Email = "alice@example.com",
CreatedAt = DateTime.Now
};
// Act: 自动映射到 DTO
var dto = ReflectionHelper.MapTo<User, UserDto>(user);
// Assert
Assert.IsNotNull(dto);
Assert.AreEqual("Alice", dto.Name);
Assert.AreEqual(25, dto.Age);
Assert.AreEqual("alice@example.com", dto.Email);
}
[TestMethod]
public void Scenario_DynamicPropertyAccess()
{
// Arrange: 模拟动态表单数据
var user = new User { Name = "Bob", Age = 30 };
var propertyUpdates = new Dictionary<string, object>
{
{ nameof(User.Name), "Updated Bob" },
{ nameof(User.Age), 31 },
{ nameof(User.Email), "bob@updated.com" }
};
// Act: 动态更新属性
foreach (var (propertyName, value) in propertyUpdates)
{
ReflectionHelper.SetPropertyValue(user, propertyName, value);
}
// Assert
Assert.AreEqual("Updated Bob", user.Name);
Assert.AreEqual(31, user.Age);
Assert.AreEqual("bob@updated.com", user.Email);
}
[TestMethod]
public void Scenario_AttributeBasedValidation()
{
// Arrange: 读取属性上的描述特性用于验证消息
var properties = typeof(User).GetProperties();
var validationMessages = new Dictionary<string, string>();
// Act: 收集所有带描述的属性
foreach (var property in properties)
{
var description = ReflectionHelper.GetAttribute<System.ComponentModel.DescriptionAttribute>(property);
if (description != null)
{
validationMessages[property.Name] = $"{description.Description}不能为空";
}
}
// Assert
Assert.IsTrue(validationMessages.ContainsKey(nameof(User.Name)));
Assert.AreEqual("用户名不能为空", validationMessages[nameof(User.Name)]);
Assert.IsTrue(validationMessages.ContainsKey(nameof(User.Age)));
Assert.AreEqual("用户年龄不能为空", validationMessages[nameof(User.Age)]);
}
[TestMethod]
public void Scenario_TypeInspection()
{
// Arrange: 检查类型信息
var type = typeof(User);
// Act: 收集类型信息
var info = new
{
IsClass = type.IsClass,
IsAbstract = type.IsAbstract,
BaseType = type.BaseType?.Name,
HasTestAttribute = ReflectionHelper.HasAttribute<TestAttribute>(type),
PropertyCount = ReflectionHelper.GetProperties<User>().Length,
IsValueType = ReflectionHelper.IsValueType(type)
};
// Assert
Assert.IsTrue(info.IsClass);
Assert.IsFalse(info.IsAbstract);
Assert.AreEqual("BaseEntity", info.BaseType);
Assert.IsTrue(info.HasTestAttribute);
Assert.IsTrue(info.PropertyCount >= 5);
Assert.IsFalse(info.IsValueType);
}
#endregion
}