using Common.Results; using Common.ExpandException; namespace Common.Test; /// /// Result 模式测试 /// 展示函数式错误处理的所有功能 /// [TestClass] public class ResultTests { #region 基础创建和状态测试 /// /// 测试:创建成功的 Result /// [TestMethod] public void Success_CreatesSuccessResult() { // Act: 创建成功的无返回值 Result var result = Result.Success(); // Assert Assert.IsTrue(result.IsSuccess); Assert.IsFalse(result.IsFailure); Assert.IsNull(result.Exception); Assert.IsNull(result.ErrorMessage); Assert.IsNull(result.ErrorCode); } /// /// 测试:创建成功的 Result /// [TestMethod] public void Success_WithValue_CreatesSuccessResultWithValue() { // Act: 创建带值的成功 Result var result = Result.Success(42); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(42, result.Value); } /// /// 测试:创建失败的 Result(使用错误消息) /// [TestMethod] public void Failure_WithMessage_CreatesFailureResult() { // Act var result = Result.Failure("Something went wrong"); // Assert Assert.IsFalse(result.IsSuccess); Assert.IsTrue(result.IsFailure); Assert.AreEqual("Something went wrong", result.ErrorMessage); Assert.IsNull(result.ErrorCode); } /// /// 测试:创建失败的 Result(使用异常) /// [TestMethod] public void Failure_WithException_CreatesFailureResult() { // Arrange var exception = new InvalidOperationException("Invalid operation"); // Act var result = Result.Failure(exception); // Assert Assert.IsTrue(result.IsFailure); Assert.AreSame(exception, result.Exception); Assert.AreEqual("Invalid operation", result.ErrorMessage); } /// /// 测试:创建带错误码的失败 Result /// [TestMethod] public void Failure_WithErrorCode_CreatesFailureResultWithCode() { // Act var result = Result.Failure(404L, "Not found"); // Assert Assert.IsTrue(result.IsFailure); Assert.AreEqual(404L, result.ErrorCode); Assert.AreEqual("Not found", result.ErrorMessage); } /// /// 测试:从 ExceptionExpand 创建失败 Result /// [TestMethod] public void Failure_WithExceptionExpand_ExtractsErrorCode() { // Arrange var exception = new ExceptionExpand(1001L, "Custom error", "Try again"); // Act var result = Result.Failure(exception); // Assert Assert.IsTrue(result.IsFailure); Assert.AreEqual(1001L, result.ErrorCode); Assert.AreEqual("Custom error", result.ErrorMessage); Assert.AreSame(exception, result.Exception); } #endregion #region Try 模式测试 /// /// 测试:Try 捕获成功的操作 /// [TestMethod] public void Try_SuccessfulAction_ReturnsSuccess() { // Arrange var executed = false; // Act var result = Result.Try(() => { executed = true; }); // Assert Assert.IsTrue(result.IsSuccess); Assert.IsTrue(executed); } /// /// 测试:Try 捕获失败的操作 /// [TestMethod] public void Try_FailingAction_ReturnsFailure() { // Act var result = Result.Try(() => { throw new InvalidOperationException("Operation failed"); }); // Assert Assert.IsTrue(result.IsFailure); Assert.IsInstanceOfType(result.Exception, typeof(InvalidOperationException)); Assert.AreEqual("Operation failed", result.ErrorMessage); } /// /// 测试:Try 捕获返回值的成功操作 /// [TestMethod] public void Try_SuccessfulFunc_ReturnsSuccessWithValue() { // Act var result = Result.Try(() => int.Parse("123")); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(123, result.Value); } /// /// 测试:Try 捕获返回值的失败操作 /// [TestMethod] public void Try_FailingFunc_ReturnsFailure() { // Act var result = Result.Try(() => int.Parse("invalid")); // Assert Assert.IsTrue(result.IsFailure); Assert.IsInstanceOfType(result.Exception, typeof(FormatException)); } /// /// 测试:TryAsync 异步操作 /// [TestMethod] public async Task TryAsync_SuccessfulTask_ReturnsSuccess() { // Act var result = await Result.TryAsync(async () => { await Task.Delay(10); }); // Assert Assert.IsTrue(result.IsSuccess); } /// /// 测试:TryAsync 异步操作返回值 /// [TestMethod] public async Task TryAsync_SuccessfulTaskWithValue_ReturnsSuccessWithValue() { // Act var result = await Result.TryAsync(async () => { await Task.Delay(10); return 42; }); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual(42, result.Value); } #endregion #region 值提取测试 /// /// 测试:GetOrNull 获取引用类型 /// [TestMethod] public void GetOrNull_SuccessResult_ReturnsValue() { // Arrange var result = Result.Success("test"); // Act var value = result.GetOrNull(); // Assert Assert.AreEqual("test", value); } /// /// 测试:GetOrNull 失败返回 null /// [TestMethod] public void GetOrNull_FailureResult_ReturnsNull() { // Arrange var result = Result.Failure("error"); // Act var value = result.GetOrNull(); // Assert Assert.IsNull(value); } /// /// 测试:GetOrNullable 获取值类型 /// [TestMethod] public void GetOrNullable_SuccessResult_ReturnsValue() { // Arrange var result = Result.Success(42); // Act var value = result.GetOrNullable(); // Assert Assert.AreEqual(42, value); } /// /// 测试:GetOrDefault 获取默认值 /// [TestMethod] public void GetOrDefault_FailureResult_ReturnsDefault() { // Arrange var result = Result.Failure("error"); // Act var value = result.GetOrDefault(999); // Assert Assert.AreEqual(999, value); } /// /// 测试:GetOrThrow 成功时返回值 /// [TestMethod] public void GetOrThrow_SuccessResult_ReturnsValue() { // Arrange var result = Result.Success(42); // Act var value = result.GetOrThrow(); // Assert Assert.AreEqual(42, value); } /// /// 测试:GetOrThrow 失败时抛出异常 /// [TestMethod] public void GetOrThrow_FailureResult_ThrowsException() { // Arrange var exception = new InvalidOperationException("test error"); var result = Result.Failure(exception); // Act & Assert var thrown = Assert.ThrowsException(() => { result.GetOrThrow(); }); Assert.AreSame(exception, thrown); } /// /// 测试:GetOrElse 使用函数提供替代值 /// [TestMethod] public void GetOrElse_FailureResult_CallsAlternativeProvider() { // Arrange var result = Result.Failure("error"); // Act var value = result.GetOrElse(() => 100); // Assert Assert.AreEqual(100, value); } #endregion #region 函数式操作测试 /// /// 测试:Map 转换成功的值 /// [TestMethod] public void Map_SuccessResult_TransformsValue() { // Arrange var result = Result.Success(10); // Act var mapped = result.Map(x => x * 2); // Assert Assert.IsTrue(mapped.IsSuccess); Assert.AreEqual(20, mapped.Value); } /// /// 测试:Map 传播失败 /// [TestMethod] public void Map_FailureResult_PropagatesFailure() { // Arrange var result = Result.Failure("error"); // Act var mapped = result.Map(x => x * 2); // Assert Assert.IsTrue(mapped.IsFailure); Assert.AreEqual("error", mapped.ErrorMessage); } /// /// 测试:Bind 链式操作 /// [TestMethod] public void Bind_SuccessResult_ChainsOperations() { // Arrange var result = Result.Success(10); // Act var bound = result .Bind(x => x > 5 ? Result.Success(x * 2) : Result.Failure("Too small")) .Bind(x => Result.Success(x.ToString())); // Assert Assert.IsTrue(bound.IsSuccess); Assert.AreEqual("20", bound.Value); } /// /// 测试:Bind 中断失败链 /// [TestMethod] public void Bind_FailureInChain_StopsExecution() { // Arrange var result = Result.Success(3); var secondBindExecuted = false; // Act var bound = result .Bind(x => x > 5 ? Result.Success(x * 2) : Result.Failure("Too small")) .Bind(x => { secondBindExecuted = true; return Result.Success(x * 2); }); // Assert Assert.IsTrue(bound.IsFailure); Assert.IsFalse(secondBindExecuted); // 第二个 Bind 不应该执行 Assert.AreEqual("Too small", bound.ErrorMessage); } /// /// 测试:Where 过滤值 /// [TestMethod] public void Where_PredicateSatisfied_ReturnsSuccess() { // Arrange var result = Result.Success(10); // Act var filtered = result.Where(x => x > 5, "Value must be greater than 5"); // Assert Assert.IsTrue(filtered.IsSuccess); Assert.AreEqual(10, filtered.Value); } /// /// 测试:Where 过滤失败 /// [TestMethod] public void Where_PredicateNotSatisfied_ReturnsFailure() { // Arrange var result = Result.Success(3); // Act var filtered = result.Where(x => x > 5, "Value must be greater than 5"); // Assert Assert.IsTrue(filtered.IsFailure); Assert.AreEqual("Value must be greater than 5", filtered.ErrorMessage); } /// /// 测试:Ensure 验证 /// [TestMethod] public void Ensure_ValidationPasses_ReturnsSuccess() { // Arrange var result = Result.Success("test@example.com"); // Act var ensured = result .Ensure(email => email.Contains("@"), "Invalid email format") .Ensure(email => email.Length > 5, "Email too short"); // Assert Assert.IsTrue(ensured.IsSuccess); } /// /// 测试:Ensure 验证失败 /// [TestMethod] public void Ensure_ValidationFails_ReturnsFailure() { // Arrange var result = Result.Success("invalid"); // Act var ensured = result.Ensure(email => email.Contains("@"), "Invalid email format"); // Assert Assert.IsTrue(ensured.IsFailure); Assert.AreEqual("Invalid email format", ensured.ErrorMessage); } #endregion #region 条件执行测试 /// /// 测试:OnSuccess 成功时执行 /// [TestMethod] public void OnSuccess_SuccessResult_ExecutesAction() { // Arrange var result = Result.Success(42); var executed = false; var capturedValue = 0; // Act result.OnSuccess(value => { executed = true; capturedValue = value; }); // Assert Assert.IsTrue(executed); Assert.AreEqual(42, capturedValue); } /// /// 测试:OnSuccess 失败时不执行 /// [TestMethod] public void OnSuccess_FailureResult_DoesNotExecute() { // Arrange var result = Result.Failure("error"); var executed = false; // Act result.OnSuccess(value => executed = true); // Assert Assert.IsFalse(executed); } /// /// 测试:OnFailure 失败时执行 /// [TestMethod] public void OnFailure_FailureResult_ExecutesAction() { // Arrange var result = Result.Failure(404L, "Not found"); var executed = false; string? capturedMessage = null; long? capturedCode = null; // Act result.OnFailure((ex, msg, code) => { executed = true; capturedMessage = msg; capturedCode = code; }); // Assert Assert.IsTrue(executed); Assert.AreEqual("Not found", capturedMessage); Assert.AreEqual(404L, capturedCode); } /// /// 测试:Match 模式匹配 /// [TestMethod] public void Match_SuccessResult_CallsSuccessHandler() { // Arrange var result = Result.Success(42); // Act var message = result.Match( value => $"Success: {value}", (ex, msg) => $"Error: {msg}" ); // Assert Assert.AreEqual("Success: 42", message); } /// /// 测试:Match 失败结果 /// [TestMethod] public void Match_FailureResult_CallsFailureHandler() { // Arrange var result = Result.Failure("Something went wrong"); // Act var message = result.Match( value => $"Success: {value}", (ex, msg) => $"Error: {msg}" ); // Assert Assert.AreEqual("Error: Something went wrong", message); } #endregion #region LINQ 查询语法测试 /// /// 测试:使用 LINQ 查询语法组合 Result /// [TestMethod] public void LinqQuery_CombinesResults() { // Arrange var result1 = Result.Success(5); var result2 = Result.Success(10); // Act: 使用 LINQ 查询语法 var combined = from x in result1 from y in result2 where x > 0 && y > 0 select x + y; // Assert Assert.IsTrue(combined.IsSuccess); Assert.AreEqual(15, combined.Value); } /// /// 测试:LINQ 查询中的失败传播 /// [TestMethod] public void LinqQuery_PropagatesFailure() { // Arrange var result1 = Result.Success(5); var result2 = Result.Failure("Error in result2"); // Act var combined = from x in result1 from y in result2 select x + y; // Assert Assert.IsTrue(combined.IsFailure); Assert.AreEqual("Error in result2", combined.ErrorMessage); } #endregion #region 错误码相关测试 /// /// 测试:HasErrorCode 检查错误码 /// [TestMethod] public void HasErrorCode_MatchingCode_ReturnsTrue() { // Arrange var result = Result.Failure(404L, "Not found"); // Act & Assert Assert.IsTrue(result.HasErrorCode(404L)); Assert.IsFalse(result.HasErrorCode(500L)); } /// /// 测试:GetErrorCodeOrDefault 获取错误码 /// [TestMethod] public void GetErrorCodeOrDefault_ReturnsCodeOrDefault() { // Arrange var failureResult = Result.Failure(404L, "Not found"); var successResult = Result.Success(42); // Act & Assert Assert.AreEqual(404L, failureResult.GetErrorCodeOrDefault()); Assert.AreEqual(-1L, successResult.GetErrorCodeOrDefault()); Assert.AreEqual(999L, successResult.GetErrorCodeOrDefault(999L)); } /// /// 测试:FromExceptionExpand 转换自定义异常 /// [TestMethod] public void FromExceptionExpand_CreatesResultWithErrorCode() { // Arrange var exception = new ExceptionExpand(1001L, "Business error", "Check input"); // Act var result = ResultExtensions.FromExceptionExpand(exception); // Assert Assert.IsTrue(result.IsFailure); Assert.AreEqual(1001L, result.ErrorCode); Assert.AreEqual("Business error", result.ErrorMessage); Assert.AreSame(exception, result.Exception); } #endregion #region 异步操作测试 /// /// 测试:MapAsync 异步转换 /// [TestMethod] public async Task MapAsync_TransformsValueAsynchronously() { // Arrange var result = Task.FromResult(Result.Success(10)); // Act var mapped = await result.MapAsync(async value => { await Task.Delay(10); return value * 2; }); // Assert Assert.IsTrue(mapped.IsSuccess); Assert.AreEqual(20, mapped.Value); } /// /// 测试:BindAsync 异步链式操作 /// [TestMethod] public async Task BindAsync_ChainsAsynchronously() { // Arrange var result = Task.FromResult(Result.Success(10)); // Act var bound = await result.BindAsync(async value => { await Task.Delay(10); return value > 5 ? Result.Success(value * 2) : Result.Failure("Too small"); }); // Assert Assert.IsTrue(bound.IsSuccess); Assert.AreEqual(20, bound.Value); } /// /// 测试:DoOnSuccessAsync 异步副作用 /// [TestMethod] public async Task DoOnSuccessAsync_ExecutesAsyncAction() { // Arrange var result = Task.FromResult(Result.Success(42)); var executed = false; // Act await result.DoOnSuccessAsync(async value => { await Task.Delay(10); executed = true; }); // Assert Assert.IsTrue(executed); } #endregion #region 实际应用场景测试 /// /// 场景测试:验证用户输入 /// 演示多步骤验证链 /// [TestMethod] public void Scenario_ValidateUserInput() { // Act: 验证有效输入 var validResult = ValidateEmail("user@example.com"); // Assert Assert.IsTrue(validResult.IsSuccess); Assert.AreEqual("user@example.com", validResult.Value); // Act: 验证无效输入 var invalidResult = ValidateEmail("invalid"); // Assert Assert.IsTrue(invalidResult.IsFailure); Assert.AreEqual("Invalid email format", invalidResult.ErrorMessage); } /// /// 场景测试:数据库操作链 /// 演示如何使用 Result 处理可能失败的操作序列 /// [TestMethod] public void Scenario_DatabaseOperationChain() { // Act: 成功的操作链 var successResult = FindUserById(1) .Bind(user => UpdateUserName(user, "NewName")) .Bind(user => SaveUser(user)) .Map(user => $"User {user.Name} saved successfully"); // Assert Assert.IsTrue(successResult.IsSuccess); Assert.AreEqual("User NewName saved successfully", successResult.Value); // Act: 失败的操作链(用户不存在) var notFoundResult = FindUserById(999) .Bind(user => UpdateUserName(user, "NewName")) .Bind(user => SaveUser(user)) .Map(user => $"User {user.Name} saved successfully"); // Assert Assert.IsTrue(notFoundResult.IsFailure); Assert.IsTrue(notFoundResult.HasErrorCode(404L)); } /// /// 场景测试:错误恢复 /// 演示使用 OrElse 提供备用逻辑 /// [TestMethod] public void Scenario_ErrorRecovery() { // Act: 主操作失败,使用备用操作 var result = TryPrimaryOperation() .OrElse(() => TryFallbackOperation()) .OrElse(() => Result.Success("Default value")); // Assert Assert.IsTrue(result.IsSuccess); Assert.AreEqual("Fallback success", result.Value); } #endregion #region 测试辅助方法 private Result ValidateEmail(string email) { return email.AsResult() .Ensure(e => !string.IsNullOrEmpty(e), "Email cannot be empty") .Ensure(e => e.Contains("@"), "Invalid email format") .Ensure(e => e.Length >= 5, "Email too short"); } private class User { public int Id { get; set; } public string Name { get; set; } = ""; } private Result FindUserById(int id) { return id == 1 ? Result.Success(new User { Id = 1, Name = "John" }) : Result.Failure(404L, "User not found"); } private Result UpdateUserName(User user, string newName) { user.Name = newName; return Result.Success(user); } private Result SaveUser(User user) { // 模拟保存成功 return Result.Success(user); } private Result TryPrimaryOperation() { return Result.Failure("Primary operation failed"); } private Result TryFallbackOperation() { return Result.Success("Fallback success"); } #endregion }