mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
docs(functional): 添加函数式编程类型文档和单元测试
- 新增 Option 类型文档,包含核心类型及扩展方法说明 - 新增 Result 类型文档,包含核心类型及扩展方法说明 - 新增 Nullable Extensions 文档,提供可空类型转换功能说明 - 添加 Option 类型单元测试,覆盖基本功能和扩展方法 - 添加 Result 类型单元测试,验证成功失败结果处理 - 添加 Nullable Extensions 单元测试,确保类型转换正确性 - 添加 Option 和 Result 扩展方法的完整测试用例 - [release ci]
This commit is contained in:
parent
1b442edadd
commit
3493d6a481
@ -0,0 +1,78 @@
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// NullableExtensions扩展方法测试类,用于验证可空类型转换为Option类型的功能
|
||||
/// 包括引用类型和值类型的可空转换测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class NullableExtensionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试引用类型可空转换 - 验证非null值转换为Some
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NullableExtensions_ReferenceType_ToOption_Should_Create_Some_For_NonNull()
|
||||
{
|
||||
// Arrange
|
||||
string? value = "Hello";
|
||||
|
||||
// Act
|
||||
var option = value.ToOption();
|
||||
|
||||
// Assert
|
||||
Assert.That(option.IsSome, Is.True);
|
||||
Assert.That(option.Value, Is.EqualTo("Hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试引用类型可空转换 - 验证null值转换为None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NullableExtensions_ReferenceType_ToOption_Should_Create_None_For_Null()
|
||||
{
|
||||
// Arrange
|
||||
string? value = null;
|
||||
|
||||
// Act
|
||||
var option = value.ToOption();
|
||||
|
||||
// Assert
|
||||
Assert.That(option.IsNone, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试值类型可空转换 - 验证有值的可空值类型转换为Some
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NullableExtensions_ValueType_ToOption_Should_Create_Some_For_HasValue()
|
||||
{
|
||||
// Arrange
|
||||
int? value = 42;
|
||||
|
||||
// Act
|
||||
var option = value.ToOption();
|
||||
|
||||
// Assert
|
||||
Assert.That(option.IsSome, Is.True);
|
||||
Assert.That(option.Value, Is.EqualTo(42));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试值类型可空转换 - 验证无值的可空值类型转换为None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NullableExtensions_ValueType_ToOption_Should_Create_None_For_NoValue()
|
||||
{
|
||||
// Arrange
|
||||
int? value = null;
|
||||
|
||||
// Act
|
||||
var option = value.ToOption();
|
||||
|
||||
// Assert
|
||||
Assert.That(option.IsNone, Is.True);
|
||||
}
|
||||
}
|
||||
181
GFramework.Core.Tests/functional/types/OptionExtensionsTests.cs
Normal file
181
GFramework.Core.Tests/functional/types/OptionExtensionsTests.cs
Normal file
@ -0,0 +1,181 @@
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// OptionExtensions扩展方法测试类,用于验证Option类型的功能扩展方法
|
||||
/// 包括映射、绑定、过滤和匹配操作等功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class OptionExtensionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试Map方法 - 验证Some值能正确映射
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Map_Should_Transform_Some_Value()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("hello");
|
||||
|
||||
// Act
|
||||
var result = option.Map(s => s.Length);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSome, Is.True);
|
||||
Assert.That(result.Value, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Map方法 - 验证None映射后仍为None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Map_Should_Return_None_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Act
|
||||
var result = option.Map(s => s.Length);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsNone, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Bind方法 - 验证Some值能正确绑定到另一个Option
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Bind_Should_Transform_Some_To_Another_Option()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("hello");
|
||||
|
||||
// Act
|
||||
var result = option.Bind(s => s.Length > 3 ? Option<int>.Some(s.Length) : Option<int>.None());
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSome, Is.True);
|
||||
Assert.That(result.Value, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Bind方法 - 验证None绑定后仍为None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Bind_Should_Return_None_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Act
|
||||
var result = option.Bind(s => Option<int>.Some(s.Length));
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsNone, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Bind方法 - 验证Some值绑定到None的情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Bind_Should_Return_None_When_Binder_Returns_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("hi"); // 长度小于3
|
||||
|
||||
// Act
|
||||
var result = option.Bind(s => s.Length > 3 ? Option<int>.Some(s.Length) : Option<int>.None());
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsNone, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Filter方法 - 验证满足条件的Some值保留
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Filter_Should_Keep_Some_When_Predicate_Matches()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("hello");
|
||||
|
||||
// Act
|
||||
var result = option.Filter(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSome, Is.True);
|
||||
Assert.That(result.Value, Is.EqualTo("hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Filter方法 - 验证不满足条件的Some值变为None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Filter_Should_Return_None_When_Predicate_Does_Not_Match()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("hi");
|
||||
|
||||
// Act
|
||||
var result = option.Filter(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsNone, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Filter方法 - 验证None过滤后仍为None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Filter_Should_Return_None_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Act
|
||||
var result = option.Filter(s => s.Length > 3);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsNone, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证Some值执行some分支
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Match_Should_Execute_Some_Branch_For_Some()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("hello");
|
||||
|
||||
// Act
|
||||
var result = option.Match(
|
||||
some: s => $"Value: {s}",
|
||||
none: () => "No value"
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("Value: hello"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证None值执行none分支
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Match_Should_Execute_None_Branch_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Act
|
||||
var result = option.Match(
|
||||
some: s => $"Value: {s}",
|
||||
none: () => "No value"
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("No value"));
|
||||
}
|
||||
}
|
||||
70
GFramework.Core.Tests/functional/types/OptionTests.cs
Normal file
70
GFramework.Core.Tests/functional/types/OptionTests.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// Option类型测试类,用于验证Option类型的基本功能
|
||||
/// 包括创建Some和None实例、值访问等功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class OptionTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试创建Some实例 - 验证非null值能正确创建Some
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Some_Should_Create_WithValue()
|
||||
{
|
||||
// Arrange
|
||||
var value = "Hello";
|
||||
|
||||
// Act
|
||||
var option = Option<string>.Some(value);
|
||||
|
||||
// Assert
|
||||
Assert.That(option.IsSome, Is.True);
|
||||
Assert.That(option.IsNone, Is.False);
|
||||
Assert.That(option.Value, Is.EqualTo(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试创建Some实例 - 验证null值时抛出异常
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_Some_Should_Throw_When_Value_Is_Null()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => Option<string>.Some(null!));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试创建None实例 - 验证能正确创建None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_None_Should_Create_Empty_Instance()
|
||||
{
|
||||
// Act
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Assert
|
||||
Assert.That(option.IsNone, Is.True);
|
||||
Assert.That(option.IsSome, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试访问None的值 - 验证抛出异常
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Option_None_Value_Access_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var _ = option.Value;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// OptionValueExtensions扩展方法测试类,用于验证Option类型值的操作扩展方法
|
||||
/// 包括获取默认值、备选Option等功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class OptionValueExtensionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试GetOrElse方法 - 验证Some值直接返回其值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_GetOrElse_Should_Return_Value_For_Some()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("actual value");
|
||||
|
||||
// Act
|
||||
var result = option.GetOrElse("default value");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("actual value"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试GetOrElse方法 - 验证None值返回默认值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_GetOrElse_Should_Return_Default_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
|
||||
// Act
|
||||
var result = option.GetOrElse("default value");
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("default value"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试GetOrElse方法(工厂函数) - 验证Some值直接返回其值(不调用工厂)
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_GetOrElse_With_Factory_Should_Return_Value_For_Some()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("actual value");
|
||||
var factoryCalled = false;
|
||||
|
||||
// Act
|
||||
var result = option.GetOrElse(() =>
|
||||
{
|
||||
factoryCalled = true;
|
||||
return "factory value";
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("actual value"));
|
||||
Assert.That(factoryCalled, Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试GetOrElse方法(工厂函数) - 验证None值调用工厂函数
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_GetOrElse_With_Factory_Should_Call_Factory_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
var factoryCalled = false;
|
||||
|
||||
// Act
|
||||
var result = option.GetOrElse(() =>
|
||||
{
|
||||
factoryCalled = true;
|
||||
return "factory value";
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo("factory value"));
|
||||
Assert.That(factoryCalled, Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试OrElse方法 - 验证Some值返回自身
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_OrElse_Should_Return_Self_For_Some()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.Some("primary value");
|
||||
var fallback = Option<string>.Some("fallback value");
|
||||
|
||||
// Act
|
||||
var result = option.OrElse(fallback);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSome, Is.True);
|
||||
Assert.That(result.Value, Is.EqualTo("primary value"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试OrElse方法 - 验证None值返回备选Option
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_OrElse_Should_Return_Fallback_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
var fallback = Option<string>.Some("fallback value");
|
||||
|
||||
// Act
|
||||
var result = option.OrElse(fallback);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSome, Is.True);
|
||||
Assert.That(result.Value, Is.EqualTo("fallback value"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试OrElse方法 - 验证None值返回备选None
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueExtensions_OrElse_Should_Return_Fallback_None_For_None()
|
||||
{
|
||||
// Arrange
|
||||
var option = Option<string>.None();
|
||||
var fallback = Option<string>.None();
|
||||
|
||||
// Act
|
||||
var result = option.OrElse(fallback);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsNone, Is.True);
|
||||
}
|
||||
}
|
||||
171
GFramework.Core.Tests/functional/types/ResultExtensionsTests.cs
Normal file
171
GFramework.Core.Tests/functional/types/ResultExtensionsTests.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// ResultExtensions扩展方法测试类,用于验证Result类型的功能扩展方法
|
||||
/// 包括映射、绑定、错误映射和匹配操作等功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ResultExtensionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试Map方法 - 验证Success值能正确映射
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Map_Should_Transform_Success_Value()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("hello");
|
||||
|
||||
// Act
|
||||
var mappedResult = result.Map(s => s.Length);
|
||||
|
||||
// Assert
|
||||
Assert.That(mappedResult.IsSuccess, Is.True);
|
||||
Assert.That(mappedResult.SuccessValue, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Map方法 - 验证Failure映射后仍保持Failure状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Map_Should_Keep_Failure_For_Failure()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Failure("error occurred");
|
||||
|
||||
// Act
|
||||
var mappedResult = result.Map(s => s.Length);
|
||||
|
||||
// Assert
|
||||
Assert.That(mappedResult.IsFailure, Is.True);
|
||||
Assert.That(mappedResult.ErrorValue, Is.EqualTo("error occurred"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Bind方法 - 验证Success值能正确绑定到另一个Result
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Bind_Should_Transform_Success_To_Another_Result()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("hello");
|
||||
|
||||
// Act
|
||||
var boundResult = result.Bind(s =>
|
||||
s.Length > 3 ? Result<int, string>.Success(s.Length) : Result<int, string>.Failure("Length too small"));
|
||||
|
||||
// Assert
|
||||
Assert.That(boundResult.IsSuccess, Is.True);
|
||||
Assert.That(boundResult.SuccessValue, Is.EqualTo(5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Bind方法 - 验证Failure绑定后仍保持Failure状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Bind_Should_Keep_Failure_For_Failure()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Failure("initial error");
|
||||
|
||||
// Act
|
||||
var boundResult = result.Bind(s => Result<int, string>.Success(s.Length));
|
||||
|
||||
// Assert
|
||||
Assert.That(boundResult.IsFailure, Is.True);
|
||||
Assert.That(boundResult.ErrorValue, Is.EqualTo("initial error"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Bind方法 - 验证Success值绑定到Failure的情况
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Bind_Should_Allow_Transition_To_Failure()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("hi"); // 长度小于3
|
||||
|
||||
// Act
|
||||
var boundResult = result.Bind(s =>
|
||||
s.Length > 3 ? Result<int, string>.Success(s.Length) : Result<int, string>.Failure("Length too small"));
|
||||
|
||||
// Assert
|
||||
Assert.That(boundResult.IsFailure, Is.True);
|
||||
Assert.That(boundResult.ErrorValue, Is.EqualTo("Length too small"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试MapError方法 - 验证Failure错误值能正确映射
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_MapError_Should_Transform_Failure_Error()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Failure("original error");
|
||||
|
||||
// Act
|
||||
var mappedErrorResult = result.MapError(err => $"Mapped: {err}");
|
||||
|
||||
// Assert
|
||||
Assert.That(mappedErrorResult.IsFailure, Is.True);
|
||||
Assert.That(mappedErrorResult.ErrorValue, Is.EqualTo("Mapped: original error"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试MapError方法 - 验证Success映射错误后仍保持Success状态
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_MapError_Should_Keep_Success_For_Success()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("success data");
|
||||
|
||||
// Act
|
||||
var mappedErrorResult = result.MapError(err => $"Mapped: {err}");
|
||||
|
||||
// Assert
|
||||
Assert.That(mappedErrorResult.IsSuccess, Is.True);
|
||||
Assert.That(mappedErrorResult.SuccessValue, Is.EqualTo("success data"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证Success值执行onSuccess分支
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Match_Should_Execute_OnSuccess_Branch_For_Success()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("success data");
|
||||
|
||||
// Act
|
||||
var matchedResult = result.Match(
|
||||
onSuccess: data => $"Success: {data}",
|
||||
onFailure: error => $"Error: {error}"
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(matchedResult, Is.EqualTo("Success: success data"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试Match方法 - 验证Failure值执行onFailure分支
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Match_Should_Execute_OnFailure_Branch_For_Failure()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Failure("something failed");
|
||||
|
||||
// Act
|
||||
var matchedResult = result.Match(
|
||||
onSuccess: data => $"Success: {data}",
|
||||
onFailure: error => $"Error: {error}"
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.That(matchedResult, Is.EqualTo("Error: something failed"));
|
||||
}
|
||||
}
|
||||
108
GFramework.Core.Tests/functional/types/ResultTests.cs
Normal file
108
GFramework.Core.Tests/functional/types/ResultTests.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using GFramework.Core.functional.types;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace GFramework.Core.Tests.functional.types;
|
||||
|
||||
/// <summary>
|
||||
/// Result类型测试类,用于验证Result类型的基本功能
|
||||
/// 包括创建Success和Failure实例、值访问等功能的测试
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ResultTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试创建Success实例 - 验证能正确创建成功结果
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Success_Should_Create_With_Value()
|
||||
{
|
||||
// Arrange
|
||||
var value = "Success data";
|
||||
|
||||
// Act
|
||||
var result = Result<string, string>.Success(value);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsSuccess, Is.True);
|
||||
Assert.That(result.IsFailure, Is.False);
|
||||
Assert.That(result.SuccessValue, Is.EqualTo(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试访问Success值 - 验证能正确获取成功值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Success_Value_Access_Should_Work()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("test");
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(result.IsSuccess, Is.True);
|
||||
Assert.That(result.SuccessValue, Is.EqualTo("test"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试访问Success的错误值 - 验证在成功状态下访问错误值抛出异常
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Success_Error_Access_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Success("success");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var _ = result.ErrorValue;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试创建Failure实例 - 验证能正确创建失败结果
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Failure_Should_Create_With_Error()
|
||||
{
|
||||
// Arrange
|
||||
var error = "Something went wrong";
|
||||
|
||||
// Act
|
||||
var result = Result<string, string>.Failure(error);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.IsFailure, Is.True);
|
||||
Assert.That(result.IsSuccess, Is.False);
|
||||
Assert.That(result.ErrorValue, Is.EqualTo(error));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试访问Failure值 - 验证能正确获取错误值
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Failure_Value_Access_Should_Work()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Failure("error");
|
||||
|
||||
// Act & Assert
|
||||
Assert.That(result.IsFailure, Is.True);
|
||||
Assert.That(result.ErrorValue, Is.EqualTo("error"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试访问Failure的成功值 - 验证在失败状态下访问成功值抛出异常
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Result_Failure_Success_Access_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var result = Result<string, string>.Failure("error");
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var _ = result.SuccessValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -207,6 +207,182 @@ object obj = "Hello";
|
||||
var str = obj.Cast<string>(); // "Hello"
|
||||
```
|
||||
|
||||
### 6. Option Type - 可选值类型
|
||||
|
||||
位于 `GFramework.Core.functional.types` 命名空间,提供表示可能存在或不存在的值的类型。
|
||||
|
||||
#### 核心类型及用法:
|
||||
|
||||
- **Option<T>** - 表示可能包含值或不包含值的类型
|
||||
|
||||
```csharp
|
||||
// 创建包含值的Option
|
||||
var someValue = Option<string>.Some("Hello");
|
||||
Console.WriteLine(someValue.IsSome); // True
|
||||
Console.WriteLine(someValue.Value); // "Hello"
|
||||
|
||||
// 创建空的Option
|
||||
var noValue = Option<string>.None();
|
||||
Console.WriteLine(noValue.IsNone); // True
|
||||
```
|
||||
|
||||
#### Option扩展方法:
|
||||
|
||||
- **Map** - 对Option中的值进行映射转换
|
||||
|
||||
```csharp
|
||||
var someValue = Option<string>.Some("hello");
|
||||
var lengthOption = someValue.Map(s => s.Length); // Some(5)
|
||||
|
||||
var noneValue = Option<string>.None();
|
||||
var noneLength = noneValue.Map(s => s.Length); // None
|
||||
```
|
||||
|
||||
- **Bind** - 将Option中的值转换为另一个Option
|
||||
|
||||
```csharp
|
||||
var someValue = Option<string>.Some("hello");
|
||||
var result = someValue.Bind(s => s.Length > 3 ? Option<int>.Some(s.Length) : Option<int>.None()); // Some(5)
|
||||
|
||||
var shortValue = Option<string>.Some("hi");
|
||||
var result2 = shortValue.Bind(s => s.Length > 3 ? Option<int>.Some(s.Length) : Option<int>.None()); // None
|
||||
```
|
||||
|
||||
- **Filter** - 根据条件过滤Option中的值
|
||||
|
||||
```csharp
|
||||
var someValue = Option<string>.Some("hello");
|
||||
var filtered = someValue.Filter(s => s.Length > 3); // Some("hello")
|
||||
var filtered2 = someValue.Filter(s => s.Length > 10); // None
|
||||
```
|
||||
|
||||
- **Match** - 模式匹配Option的状态
|
||||
|
||||
```csharp
|
||||
var someValue = Option<string>.Some("hello");
|
||||
var result = someValue.Match(
|
||||
some: s => $"Value: {s}",
|
||||
none: () => "No value"
|
||||
); // "Value: hello"
|
||||
|
||||
var noneValue = Option<string>.None();
|
||||
var result2 = noneValue.Match(
|
||||
some: s => $"Value: {s}",
|
||||
none: () => "No value"
|
||||
); // "No value"
|
||||
```
|
||||
|
||||
- **GetOrElse** - 获取值或返回默认值
|
||||
|
||||
```csharp
|
||||
var someValue = Option<string>.Some("hello");
|
||||
var value1 = someValue.GetOrElse("default"); // "hello"
|
||||
|
||||
var noneValue = Option<string>.None();
|
||||
var value2 = noneValue.GetOrElse("default"); // "default"
|
||||
```
|
||||
|
||||
- **OrElse** - 当前Option为空时返回备选Option
|
||||
|
||||
```csharp
|
||||
var someValue = Option<string>.Some("primary");
|
||||
var result1 = someValue.OrElse(Option<string>.Some("fallback")); // Some("primary")
|
||||
|
||||
var noneValue = Option<string>.None();
|
||||
var result2 = noneValue.OrElse(Option<string>.Some("fallback")); // Some("fallback")
|
||||
```
|
||||
|
||||
### 7. Result Type - 结果类型
|
||||
|
||||
位于 `GFramework.Core.functional.types` 命名空间,提供表示成功或失败结果的类型。
|
||||
|
||||
#### 核心类型及用法:
|
||||
|
||||
- **Result<TSuccess, TError>** - 表示可能成功或失败的计算结果
|
||||
|
||||
```csharp
|
||||
// 创建成功的结果
|
||||
var successResult = Result<string, string>.Success("Operation successful");
|
||||
Console.WriteLine(successResult.IsSuccess); // True
|
||||
Console.WriteLine(successResult.SuccessValue); // "Operation successful"
|
||||
|
||||
// 创建失败的结果
|
||||
var failureResult = Result<string, string>.Failure("Operation failed");
|
||||
Console.WriteLine(failureResult.IsFailure); // True
|
||||
Console.WriteLine(failureResult.ErrorValue); // "Operation failed"
|
||||
```
|
||||
|
||||
#### Result扩展方法:
|
||||
|
||||
- **Map** - 对成功值进行映射转换
|
||||
|
||||
```csharp
|
||||
var successResult = Result<string, string>.Success("hello");
|
||||
var lengthResult = successResult.Map(s => s.Length); // Success(5)
|
||||
|
||||
var failureResult = Result<string, string>.Failure("error");
|
||||
var lengthResult2 = failureResult.Map(s => s.Length); // Failure("error")
|
||||
```
|
||||
|
||||
- **Bind** - 将成功值转换为另一个Result
|
||||
|
||||
```csharp
|
||||
var successResult = Result<string, string>.Success("hello");
|
||||
var result = successResult.Bind(s =>
|
||||
s.Length > 3 ?
|
||||
Result<int, string>.Success(s.Length) :
|
||||
Result<int, string>.Failure("Length too small"));
|
||||
// Result<int, string>.Success(5)
|
||||
```
|
||||
|
||||
- **MapError** - 对错误值进行映射转换
|
||||
|
||||
```csharp
|
||||
var failureResult = Result<string, string>.Failure("original error");
|
||||
var mappedErrorResult = failureResult.MapError(err => $"Mapped: {err}");
|
||||
// Result<string, string>.Failure("Mapped: original error")
|
||||
```
|
||||
|
||||
- **Match** - 模式匹配Result的状态
|
||||
|
||||
```csharp
|
||||
var successResult = Result<string, string>.Success("data");
|
||||
var result = successResult.Match(
|
||||
onSuccess: data => $"Success: {data}",
|
||||
onFailure: error => $"Error: {error}"
|
||||
); // "Success: data"
|
||||
|
||||
var failureResult = Result<string, string>.Failure("error");
|
||||
var result2 = failureResult.Match(
|
||||
onSuccess: data => $"Success: {data}",
|
||||
onFailure: error => $"Error: {error}"
|
||||
); // "Error: error"
|
||||
```
|
||||
|
||||
### 8. Nullable Extensions - 可空类型扩展
|
||||
|
||||
位于 `GFramework.Core.functional.types` 命名空间,提供将可空类型转换为Option类型的方法。
|
||||
|
||||
#### 方法列表及用法:
|
||||
|
||||
- **ToOption** - 将可空类型转换为Option
|
||||
|
||||
```csharp
|
||||
// 引用类型可空转换
|
||||
string? stringValue = "Hello";
|
||||
var someOption = stringValue.ToOption(); // Some("Hello")
|
||||
|
||||
string? nullString = null;
|
||||
var noneOption = nullString.ToOption(); // None
|
||||
|
||||
// 值类型可空转换
|
||||
int? intValue = 42;
|
||||
var someIntOption = intValue.ToOption(); // Some(42)
|
||||
|
||||
int? nullInt = null;
|
||||
var noneIntOption = nullInt.ToOption(); // None
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 链式操作
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user