GFramework/GFramework.Core.Tests/Extensions/CollectionExtensionsTests.cs
gewuyou ff553977e3 chore(license): 补齐 Apache-2.0 文件头治理
- 新增许可证文件头检查与修复脚本

- 补充维护者手动修复 PR 工作流和 CI 校验

- 更新贡献指南中的文件头说明

- 补齐仓库维护源码和配置文件的许可证声明
2026-05-03 19:39:49 +08:00

255 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0
using GFramework.Core.Extensions;
using NUnit.Framework;
namespace GFramework.Core.Tests.Extensions;
/// <summary>
/// 测试 CollectionExtensions 扩展方法的功能
/// </summary>
[TestFixture]
public class CollectionExtensionsTests
{
/// <summary>
/// 测试ForEach方法对每个元素执行指定操作
/// </summary>
[Test]
public void ForEach_Should_Execute_Action_For_Each_Element()
{
// Arrange
var numbers = new[] { 1, 2, 3, 4, 5 };
var sum = 0;
// Act
numbers.ForEach(n => sum += n);
// Assert
Assert.That(sum, Is.EqualTo(15));
}
/// <summary>
/// 测试ForEach方法在源为null时抛出ArgumentNullException
/// </summary>
[Test]
public void ForEach_Should_Throw_ArgumentNullException_When_Source_Is_Null()
{
// Arrange
IEnumerable<int>? numbers = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => numbers!.ForEach(n => { }));
}
/// <summary>
/// 测试ForEach方法在操作为null时抛出ArgumentNullException
/// </summary>
[Test]
public void ForEach_Should_Throw_ArgumentNullException_When_Action_Is_Null()
{
// Arrange
var numbers = new[] { 1, 2, 3 };
// Act & Assert
Assert.Throws<ArgumentNullException>(() => numbers.ForEach(null!));
}
/// <summary>
/// 测试IsNullOrEmpty方法在源为null时返回true
/// </summary>
[Test]
public void IsNullOrEmpty_Should_Return_True_When_Source_Is_Null()
{
// Arrange
IEnumerable<int>? numbers = null;
// Act
var result = numbers.IsNullOrEmpty();
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// 测试IsNullOrEmpty方法在源为空时返回true
/// </summary>
[Test]
public void IsNullOrEmpty_Should_Return_True_When_Source_Is_Empty()
{
// Arrange
var numbers = Array.Empty<int>();
// Act
var result = numbers.IsNullOrEmpty();
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// 测试IsNullOrEmpty方法在源有元素时返回false
/// </summary>
[Test]
public void IsNullOrEmpty_Should_Return_False_When_Source_Has_Elements()
{
// Arrange
var numbers = new[] { 1, 2, 3 };
// Act
var result = numbers.IsNullOrEmpty();
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// 测试WhereNotNull方法过滤掉null元素
/// </summary>
[Test]
public void WhereNotNull_Should_Filter_Out_Null_Elements()
{
// Arrange
var items = new string?[] { "a", null, "b", null, "c" };
// Act
var result = items.WhereNotNull().ToArray();
// Assert
Assert.That(result.Length, Is.EqualTo(3));
Assert.That(result, Is.EqualTo(new[] { "a", "b", "c" }));
}
/// <summary>
/// 测试WhereNotNull方法在所有元素都为null时返回空集合
/// </summary>
[Test]
public void WhereNotNull_Should_Return_Empty_Collection_When_All_Elements_Are_Null()
{
// Arrange
var items = new string?[] { null, null, null };
// Act
var result = items.WhereNotNull().ToArray();
// Assert
Assert.That(result, Is.Empty);
}
/// <summary>
/// 测试WhereNotNull方法在源为null时抛出ArgumentNullException
/// </summary>
[Test]
public void WhereNotNull_Should_Throw_ArgumentNullException_When_Source_Is_Null()
{
// Arrange
IEnumerable<string?>? items = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => items!.WhereNotNull().ToArray());
}
/// <summary>
/// 测试ToDictionarySafe方法创建字典
/// </summary>
[Test]
public void ToDictionarySafe_Should_Create_Dictionary()
{
// Arrange
var items = new[] { ("a", 1), ("b", 2), ("c", 3) };
// Act
var result = items.ToDictionarySafe(x => x.Item1, x => x.Item2);
// Assert
Assert.That(result.Count, Is.EqualTo(3));
Assert.That(result["a"], Is.EqualTo(1));
Assert.That(result["b"], Is.EqualTo(2));
Assert.That(result["c"], Is.EqualTo(3));
}
/// <summary>
/// 测试ToDictionarySafe保持具体Dictionary返回类型避免公开API继续收窄。
/// </summary>
[Test]
public void ToDictionarySafe_Should_Preserve_Concrete_Return_Type()
{
var method = typeof(GFramework.Core.Extensions.CollectionExtensions)
.GetMethods()
.Single(static method => string.Equals(method.Name, nameof(GFramework.Core.Extensions.CollectionExtensions.ToDictionarySafe), StringComparison.Ordinal));
var methodGenericArguments = method.GetGenericArguments();
var returnTypeGenericArguments = method.ReturnType.GetGenericArguments();
Assert.Multiple(() =>
{
Assert.That(method.IsGenericMethodDefinition, Is.True);
Assert.That(method.ReturnType.IsGenericType, Is.True);
Assert.That(method.ReturnType.GetGenericTypeDefinition(), Is.EqualTo(typeof(Dictionary<,>)));
Assert.That(methodGenericArguments.Select(static argument => argument.Name), Is.EqualTo(new[] { "T", "TKey", "TValue" }));
Assert.That(returnTypeGenericArguments, Has.Length.EqualTo(2));
Assert.That(returnTypeGenericArguments[0], Is.SameAs(methodGenericArguments[1]));
Assert.That(returnTypeGenericArguments[1], Is.SameAs(methodGenericArguments[2]));
});
}
/// <summary>
/// 测试ToDictionarySafe方法在存在重复键时覆盖前面的值
/// </summary>
[Test]
public void ToDictionarySafe_Should_Overwrite_Duplicate_Keys()
{
// Arrange
var items = new[] { ("a", 1), ("b", 2), ("a", 3) };
// Act
var result = items.ToDictionarySafe(x => x.Item1, x => x.Item2);
// Assert
Assert.That(result.Count, Is.EqualTo(2));
Assert.That(result["a"], Is.EqualTo(3)); // 最后一个值
Assert.That(result["b"], Is.EqualTo(2));
}
/// <summary>
/// 测试ToDictionarySafe方法在源为null时抛出ArgumentNullException
/// </summary>
[Test]
public void ToDictionarySafe_Should_Throw_ArgumentNullException_When_Source_Is_Null()
{
// Arrange
IEnumerable<(string, int)>? items = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
items!.ToDictionarySafe(x => x.Item1, x => x.Item2));
}
/// <summary>
/// 测试ToDictionarySafe方法在键选择器为null时抛出ArgumentNullException
/// </summary>
[Test]
public void ToDictionarySafe_Should_Throw_ArgumentNullException_When_KeySelector_Is_Null()
{
// Arrange
var items = new[] { ("a", 1), ("b", 2) };
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
items.ToDictionarySafe<(string, int), string, int>(null!, x => x.Item2));
}
/// <summary>
/// 测试ToDictionarySafe方法在值选择器为null时抛出ArgumentNullException
/// </summary>
[Test]
public void ToDictionarySafe_Should_Throw_ArgumentNullException_When_ValueSelector_Is_Null()
{
// Arrange
var items = new[] { ("a", 1), ("b", 2) };
// Act & Assert
Assert.Throws<ArgumentNullException>(() =>
items.ToDictionarySafe<(string, int), string, int>(x => x.Item1, null!));
}
}