From 31464ea9c649a323c88a073eab23774fbe03c8ce Mon Sep 17 00:00:00 2001 From: Iliyan Angelov <51085480+IliyanAng@users.noreply.github.com> Date: Tue, 29 Aug 2023 19:32:36 +0200 Subject: [PATCH] Add support for single validation error with Result.Invalid (#144) * Add support for single validation error with Result.Invalid - Support for single validation error in the Result.Invalid method - Added unit tests to test the behavior * Update src/Ardalis.Result/Result.Void.cs * Update src/Ardalis.Result/Result.cs --------- Co-authored-by: Steve Smith --- src/Ardalis.Result/Result.Void.cs | 10 ++++++++++ src/Ardalis.Result/Result.cs | 10 ++++++++++ .../ResultConstructor.cs | 10 +++++++++- .../ResultVoidConstructor.cs | 20 +++++++++++++++++-- .../Ardalis.Result.UnitTests/ResultVoidMap.cs | 14 ++++++++++++- .../ResultVoidToResultOfT.cs | 20 ++++++++++++++++++- 6 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/Ardalis.Result/Result.Void.cs b/src/Ardalis.Result/Result.Void.cs index 7b0ee94..7c69e74 100644 --- a/src/Ardalis.Result/Result.Void.cs +++ b/src/Ardalis.Result/Result.Void.cs @@ -77,6 +77,16 @@ public static Result ErrorWithCorrelationId(string correlationId, params string[ }; } + /// + /// Represents the validation error that prevents the underlying service from completing. + /// + /// The validation error encountered + /// A Result + public new static Result Invalid(ValidationError validationError) + { + return new Result(ResultStatus.Invalid) { ValidationErrors = { validationError } }; + } + /// /// Represents validation errors that prevent the underlying service from completing. /// diff --git a/src/Ardalis.Result/Result.cs b/src/Ardalis.Result/Result.cs index 5bce85d..845c02e 100644 --- a/src/Ardalis.Result/Result.cs +++ b/src/Ardalis.Result/Result.cs @@ -111,6 +111,16 @@ public static Result Error(params string[] errorMessages) return new Result(ResultStatus.Error) { Errors = errorMessages }; } + /// + /// Represents a validation error that prevents the underlying service from completing. + /// + /// The validation error encountered + /// A Result + public static Result Invalid(ValidationError validationError) + { + return new Result(ResultStatus.Invalid) { ValidationErrors = { validationError } }; + } + /// /// Represents validation errors that prevent the underlying service from completing. /// diff --git a/tests/Ardalis.Result.UnitTests/ResultConstructor.cs b/tests/Ardalis.Result.UnitTests/ResultConstructor.cs index 639f416..029e6d2 100644 --- a/tests/Ardalis.Result.UnitTests/ResultConstructor.cs +++ b/tests/Ardalis.Result.UnitTests/ResultConstructor.cs @@ -207,10 +207,18 @@ public void InitializedIsSuccessFalseForForbiddenFactoryCall() Assert.False(result.IsSuccess); } + [Fact] + public void InitializedIsSuccessFalseForInvalidListFactoryCall() + { + var result = Result.Invalid(new List()); + + Assert.False(result.IsSuccess); + } + [Fact] public void InitializedIsSuccessFalseForInvalidFactoryCall() { - var result = Result.Invalid(null); + var result = Result.Invalid(new ValidationError()); Assert.False(result.IsSuccess); } diff --git a/tests/Ardalis.Result.UnitTests/ResultVoidConstructor.cs b/tests/Ardalis.Result.UnitTests/ResultVoidConstructor.cs index 48b4875..0dcc839 100644 --- a/tests/Ardalis.Result.UnitTests/ResultVoidConstructor.cs +++ b/tests/Ardalis.Result.UnitTests/ResultVoidConstructor.cs @@ -1,5 +1,4 @@ using FluentAssertions; -using System; using System.Collections.Generic; using System.Linq; using Xunit; @@ -73,7 +72,7 @@ public void InitializesErrorResultWithCorrelationIdWithFactoryMethod() } [Fact] - public void InitializesInvalidResultWithFactoryMethod() + public void InitializesInvalidResultWithMultipleValidationErrorsWithFactoryMethod() { var validationErrors = new List { @@ -98,6 +97,23 @@ public void InitializesInvalidResultWithFactoryMethod() result.ValidationErrors.Should().ContainEquivalentOf(new ValidationError { ErrorMessage = "PostalCode cannot exceed 10 characters", Identifier = "postalCode" }); } + [Fact] + public void InitializesInvalidResultWithSingleValidationErrorWithFactoryMethod() + { + var validationError = new ValidationError + { + Identifier = "name", + ErrorMessage = "Name is required" + }; + + var result = Result.Invalid(validationError); + + Assert.Null(result.Value); + Assert.Equal(ResultStatus.Invalid, result.Status); + + result.ValidationErrors.Should().ContainEquivalentOf(new ValidationError { ErrorMessage = "Name is required", Identifier = "name" }); + } + [Fact] public void InitializesNotFoundResultWithFactoryMethod() { diff --git a/tests/Ardalis.Result.UnitTests/ResultVoidMap.cs b/tests/Ardalis.Result.UnitTests/ResultVoidMap.cs index d62999d..aaaf8b7 100644 --- a/tests/Ardalis.Result.UnitTests/ResultVoidMap.cs +++ b/tests/Ardalis.Result.UnitTests/ResultVoidMap.cs @@ -1,4 +1,5 @@ using FluentAssertions; +using System.Collections.Generic; using Xunit; namespace Ardalis.Result.UnitTests @@ -48,10 +49,21 @@ public void ShouldProduceForbidden() actual.Value.Should().BeNull(); } + [Fact] + public void ShouldProduceInvalidWithEmptyList() + { + var result = Result.Invalid(new List()); + + var actual = result.Map(_ => "This should be ignored"); + + actual.Status.Should().Be(ResultStatus.Invalid); + actual.Value.Should().BeNull(); + } + [Fact] public void ShouldProduceInvalid() { - var result = Result.Invalid(new()); + var result = Result.Invalid(new ValidationError()); var actual = result.Map(_ => "This should be ignored"); diff --git a/tests/Ardalis.Result.UnitTests/ResultVoidToResultOfT.cs b/tests/Ardalis.Result.UnitTests/ResultVoidToResultOfT.cs index 593939e..f596bdf 100644 --- a/tests/Ardalis.Result.UnitTests/ResultVoidToResultOfT.cs +++ b/tests/Ardalis.Result.UnitTests/ResultVoidToResultOfT.cs @@ -23,7 +23,7 @@ public void ConvertFromErrorResultOfUnit(params string[] errors) } [Fact] - public void ConvertFromInvalidResultOfUnit() + public void ConvertFromInvalidResultOfUnitWithValidationErrorList() { var validationErrors = new List { @@ -49,6 +49,24 @@ public void ConvertFromInvalidResultOfUnit() result.ValidationErrors.Should().ContainEquivalentOf(new ValidationError { ErrorMessage = "PostalCode cannot exceed 10 characters", Identifier = "postalCode" }); } + [Fact] + public void ConvertFromInvalidResultOfUnitWithValidationError() + { + var validationError = new ValidationError + { + Identifier = "name", + ErrorMessage = "Name is required" + }; + + var result = DoBusinessOperationExample(Result.Invalid(validationError)); + + Assert.Null(result.Value); + Assert.Equal(ResultStatus.Invalid, result.Status); + + result.Status.Should().Be(ResultStatus.Invalid); + result.ValidationErrors.Should().ContainEquivalentOf(new ValidationError { ErrorMessage = "Name is required", Identifier = "name" }); + } + [Fact] public void ConvertFromNotFoundResultOfUnit() {