diff --git a/FirstClassErrors.RequestBinder.UnitTests/BindingContractTests.cs b/FirstClassErrors.RequestBinder.UnitTests/BindingContractTests.cs index e5fc3c9..aa4a89e 100644 --- a/FirstClassErrors.RequestBinder.UnitTests/BindingContractTests.cs +++ b/FirstClassErrors.RequestBinder.UnitTests/BindingContractTests.cs @@ -3,6 +3,8 @@ using System.Linq.Expressions; using System.Reflection; +using FirstClassErrors.Testing; + using NFluent; #endregion @@ -30,8 +32,8 @@ public void ConverterMayFailWithAPrimaryPortError() { var bind = Bind.PropertiesOf(Request()).FailWith(BookingEnvelopeError.CommandInvalid); bind.SimpleProperty(r => r.GuestEmail).AsRequired(_ => Outcome.Failure( - PrimaryPortError.Create(ErrorCode.Create("TEST_PORT_LEVEL_REJECTION"), "Rejected at the port.", Transience.NonTransient) - .WithPublicMessage("Rejected."))); + PrimaryPortError.Create(ErrorCode.Create("TEST_PORT_LEVEL_REJECTION"), Any.DiagnosticMessage(), Any.Transience()) + .WithPublicMessage(Any.ShortMessage()))); Outcome outcome = bind.New(_ => "never"); Error invalid = outcome.Error!.InnerErrors.Single(); @@ -44,9 +46,9 @@ public void ConverterFailingWithAnotherFamilyIsABug() { var bind = Bind.PropertiesOf(Request()).FailWith(BookingEnvelopeError.CommandInvalid); InfrastructureError foreignFamily = - InfrastructureError.Create(ErrorCode.Create("TEST_FOREIGN_FAMILY"), "A family the port envelope cannot hold.", - InteractionDirection.Outgoing, Transience.Unknown) - .WithPublicMessage("Foreign."); + InfrastructureError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), + Any.InteractionDirection(), Transience.Unknown) + .WithPublicMessage(Any.ShortMessage()); InvalidOperationException exception = Assert.Throws( () => { bind.SimpleProperty(r => r.GuestEmail).AsRequired(_ => Outcome.Failure(foreignFamily)); }); @@ -87,9 +89,9 @@ public void BareNestedElementFailureIsWrapped() { } private static PrimaryPortError LeafPortError() { - return PrimaryPortError.Create(ErrorCode.Create("TEST_NESTED_PORT_LEAF"), "A bare port-level leaf, not a build-terminal envelope.", - Transience.NonTransient) - .WithPublicMessage("Rejected."); + return PrimaryPortError.Create(ErrorCode.Create("TEST_NESTED_PORT_LEAF"), Any.DiagnosticMessage(), + Any.Transience()) + .WithPublicMessage(Any.ShortMessage()); } [Fact(DisplayName = "A required nested binding that fails with a bare PrimaryPortError leaf (not its build-terminal envelope) is wrapped, so the path survives.")] diff --git a/FirstClassErrors.RequestBinder.UnitTests/RequestBinderTests.cs b/FirstClassErrors.RequestBinder.UnitTests/RequestBinderTests.cs index ad52e17..5826766 100644 --- a/FirstClassErrors.RequestBinder.UnitTests/RequestBinderTests.cs +++ b/FirstClassErrors.RequestBinder.UnitTests/RequestBinderTests.cs @@ -2,6 +2,8 @@ using System.Reflection; +using FirstClassErrors.Testing; + using NFluent; #endregion @@ -24,8 +26,8 @@ private static Outcome BindStay(RequestBinder stay) { private static Outcome AssembleStay(BookingDate checkIn, BookingDate checkOut) { return checkOut.Value > checkIn.Value ? Outcome.Success(new Stay(checkIn, checkOut)) - : Outcome.Failure(DomainError.Create(CheckOutNotAfterCheckIn, "Check-out must be after check-in.") - .WithPublicMessage("The stay dates are inconsistent.")); + : Outcome.Failure(DomainError.Create(CheckOutNotAfterCheckIn, Any.DiagnosticMessage()) + .WithPublicMessage(Any.ShortMessage())); } [Fact(DisplayName = "New assembles the command exactly once when every property bound.")] diff --git a/FirstClassErrors.UnitTests/ErrorCodeFactory.cs b/FirstClassErrors.UnitTests/ErrorCodeFactory.cs deleted file mode 100644 index 1734129..0000000 --- a/FirstClassErrors.UnitTests/ErrorCodeFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace FirstClassErrors.UnitTests { - - public static class ErrorCodeFactory { - - #region Static members - - public static ErrorCode CreateAny() { - return ErrorCode.Create("ANY"); - } - - #endregion - - } - -} \ No newline at end of file diff --git a/FirstClassErrors.UnitTests/ErrorCodeTests.cs b/FirstClassErrors.UnitTests/ErrorCodeTests.cs index 3a32745..99e9073 100644 --- a/FirstClassErrors.UnitTests/ErrorCodeTests.cs +++ b/FirstClassErrors.UnitTests/ErrorCodeTests.cs @@ -1,5 +1,7 @@ #region Usings declarations +using FirstClassErrors.Testing; + using JetBrains.Annotations; using NFluent; @@ -72,7 +74,7 @@ public void ErrorCodesWithDifferentCodesAreNotEqual() { [Fact(DisplayName = "An error code compared to null is not equal.")] public void ErrorCodeComparedToNullIsNotEqual() { // Setup - ErrorCode? errorCode = ErrorCode.Create("NULL_TEST"); + ErrorCode? errorCode = Any.ErrorCode(); // Exercise bool result = errorCode.Equals(null); diff --git a/FirstClassErrors.UnitTests/ErrorContextImmutabilityTests.cs b/FirstClassErrors.UnitTests/ErrorContextImmutabilityTests.cs index 83cb620..e981da2 100644 --- a/FirstClassErrors.UnitTests/ErrorContextImmutabilityTests.cs +++ b/FirstClassErrors.UnitTests/ErrorContextImmutabilityTests.cs @@ -2,6 +2,8 @@ using System.Diagnostics.CodeAnalysis; +using FirstClassErrors.Testing; + using JetBrains.Annotations; using NFluent; @@ -31,8 +33,8 @@ public void Dispose() { public void TheContextValuesAreReadOnlyAndCannotBeMutated() { // Setup ErrorContextKey key = ErrorContextKey.Create("K"); - ErrorContext context = DomainError.Create(ErrorCode.Unspecified, "m", - ctx => ctx.Add(key, "value")).WithPublicMessage("m").Context; + ErrorContext context = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), + ctx => ctx.Add(key, Any.String())).WithPublicMessage(Any.ShortMessage()).Context; // Exercise & verify Check.ThatCode(() => ((IDictionary)context.Values).Clear()) @@ -43,8 +45,8 @@ public void TheContextValuesAreReadOnlyAndCannotBeMutated() { public void AnEntryWhoseStoredValueIsNullIsPresentButReportedAsNotFound() { // Setup ErrorContextKey key = ErrorContextKey.Create("K"); - ErrorContext context = DomainError.Create(ErrorCode.Unspecified, "m", - ctx => ctx.Add(key, null)).WithPublicMessage("m").Context; + ErrorContext context = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), + ctx => ctx.Add(key, null)).WithPublicMessage(Any.ShortMessage()).Context; // Exercise bool found = context.TryGet(key, out _); diff --git a/FirstClassErrors.UnitTests/ErrorDefensiveTests.cs b/FirstClassErrors.UnitTests/ErrorDefensiveTests.cs index 51d7a3d..fe74bc8 100644 --- a/FirstClassErrors.UnitTests/ErrorDefensiveTests.cs +++ b/FirstClassErrors.UnitTests/ErrorDefensiveTests.cs @@ -2,6 +2,8 @@ using System.Diagnostics.CodeAnalysis; +using FirstClassErrors.Testing; + using JetBrains.Annotations; using NFluent; @@ -30,7 +32,7 @@ public void Dispose() { [Fact(DisplayName = "A null error code is replaced by the unspecified error code.")] public void ANullErrorCodeIsReplacedByTheUnspecifiedErrorCode() { // Exercise - DomainError error = DomainError.Create(null!, "diagnostic").WithPublicMessage("short"); + DomainError error = DomainError.Create(null!, Any.DiagnosticMessage()).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.Code).IsSameReferenceAs(ErrorCode.Unspecified); @@ -39,7 +41,7 @@ public void ANullErrorCodeIsReplacedByTheUnspecifiedErrorCode() { [Fact(DisplayName = "A null diagnostic message is replaced by a fallback sentinel.")] public void ANullDiagnosticMessageIsReplacedByAFallbackSentinel() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, null!).WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), null!).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.DiagnosticMessage).IsEqualTo(Error.MissingDiagnosticMessage); @@ -51,7 +53,7 @@ public void ANullDiagnosticMessageIsReplacedByAFallbackSentinel() { [InlineData(" ")] public void AnEmptyOrWhitespaceDiagnosticMessageIsReplacedByAFallbackSentinel(string value) { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, value).WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), value).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.DiagnosticMessage).IsEqualTo(Error.MissingDiagnosticMessage); @@ -60,7 +62,7 @@ public void AnEmptyOrWhitespaceDiagnosticMessageIsReplacedByAFallbackSentinel(st [Fact(DisplayName = "The diagnostic message is trimmed.")] public void TheDiagnosticMessageIsTrimmed() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, " hello ").WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), " hello ").WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.DiagnosticMessage).IsEqualTo("hello"); @@ -69,7 +71,7 @@ public void TheDiagnosticMessageIsTrimmed() { [Fact(DisplayName = "A null short message is replaced by a fallback sentinel.")] public void ANullShortMessageIsReplacedByAFallbackSentinel() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage(null!); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(null!); // Verify Check.That(error.ShortMessage).IsEqualTo(Error.MissingShortMessage); @@ -81,7 +83,7 @@ public void ANullShortMessageIsReplacedByAFallbackSentinel() { [InlineData(" ")] public void AnEmptyOrWhitespaceShortMessageIsReplacedByAFallbackSentinel(string value) { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage(value); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(value); // Verify Check.That(error.ShortMessage).IsEqualTo(Error.MissingShortMessage); @@ -90,7 +92,7 @@ public void AnEmptyOrWhitespaceShortMessageIsReplacedByAFallbackSentinel(string [Fact(DisplayName = "A missing diagnostic message is recorded in the context under #MISSING_REQUIRED_MESSAGE.")] public void AMissingDiagnosticMessageIsRecordedInTheContext() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, null!).WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), null!).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.Context.Values.ContainsKey(ErrorContextKey.MissingRequiredMessages)).IsTrue(); @@ -102,7 +104,7 @@ public void AMissingDiagnosticMessageIsRecordedInTheContext() { [Fact(DisplayName = "Missing diagnostic and short messages are both recorded in the context.")] public void MissingDiagnosticAndShortMessagesAreBothRecordedInTheContext() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, null!).WithPublicMessage(null!); + DomainError error = DomainError.Create(Any.ErrorCode(), null!).WithPublicMessage(null!); // Verify IReadOnlyList missing = (IReadOnlyList)error.Context.Values[ErrorContextKey.MissingRequiredMessages]!; @@ -112,7 +114,7 @@ public void MissingDiagnosticAndShortMessagesAreBothRecordedInTheContext() { [Fact(DisplayName = "Present mandatory messages leave no #MISSING_REQUIRED_MESSAGE entry in the context.")] public void PresentMandatoryMessagesLeaveNoMissingEntryInTheContext() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.Context.Values.ContainsKey(ErrorContextKey.MissingRequiredMessages)).IsFalse(); @@ -121,7 +123,7 @@ public void PresentMandatoryMessagesLeaveNoMissingEntryInTheContext() { [Fact(DisplayName = "The short message is trimmed.")] public void TheShortMessageIsTrimmed() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage(" short "); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(" short "); // Verify Check.That(error.ShortMessage).IsEqualTo("short"); @@ -130,7 +132,7 @@ public void TheShortMessageIsTrimmed() { [Fact(DisplayName = "A null detailed message leaves the detailed message null.")] public void ANullDetailedMessageLeavesTheDetailedMessageNull() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage("short", null); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(Any.ShortMessage(), null); // Verify Check.That(error.DetailedMessage).IsNull(); @@ -142,7 +144,7 @@ public void ANullDetailedMessageLeavesTheDetailedMessageNull() { [InlineData(" ")] public void AnEmptyOrWhitespaceDetailedMessageLeavesTheDetailedMessageNull(string value) { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage("short", value); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(Any.ShortMessage(), value); // Verify Check.That(error.DetailedMessage).IsNull(); @@ -151,7 +153,7 @@ public void AnEmptyOrWhitespaceDetailedMessageLeavesTheDetailedMessageNull(strin [Fact(DisplayName = "A detailed message is trimmed when provided.")] public void ADetailedMessageIsTrimmedWhenProvided() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic").WithPublicMessage("short", " detailed "); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage()).WithPublicMessage(Any.ShortMessage(), " detailed "); // Verify Check.That(error.DetailedMessage).IsEqualTo("detailed"); @@ -160,8 +162,8 @@ public void ADetailedMessageIsTrimmedWhenProvided() { [Fact(DisplayName = "A configure-context delegate that throws is captured into the context.")] public void AConfigureContextDelegateThatThrowsIsCapturedIntoTheContext() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic", _ => throw new InvalidOperationException("boom")) - .WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), _ => throw new InvalidOperationException("boom")) + .WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.Context.IsEmpty).IsFalse(); @@ -178,12 +180,12 @@ public void AConfigureContextDelegateThatThrowsPreservesTheEntriesAddedBeforeThe ErrorContextKey beforeKey = ErrorContextKey.Create("BeforeFailure"); // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic", builder => { + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), builder => { builder.Add(beforeKey, "kept"); throw new InvalidOperationException("boom"); }) - .WithPublicMessage("short"); + .WithPublicMessage(Any.ShortMessage()); // Verify — the entry added before the failure survives alongside the captured exception. bool found = error.Context.TryGet(beforeKey, out string? kept); @@ -198,7 +200,7 @@ public void InnerErrorsAreStoredAsADefensiveCopyOfTheProvidedCollection() { List innerErrors = new() { ErrorFactory.Domain(ErrorCode.Unspecified, "first") }; - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic", innerErrors).WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), innerErrors).WithPublicMessage(Any.ShortMessage()); // Exercise innerErrors.Add(ErrorFactory.Domain(ErrorCode.Unspecified, "second")); @@ -217,7 +219,7 @@ public void NullEntriesInTheProvidedInnerErrorsCollectionAreFilteredOut() { }; // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic", innerErrors).WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), innerErrors).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.InnerErrors).CountIs(2); @@ -230,7 +232,7 @@ public void ACollectionMadeOnlyOfNullInnerErrorsYieldsAnEmptyInnerErrorsList() { List innerErrors = new() { null!, null! }; // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "diagnostic", innerErrors).WithPublicMessage("short"); + DomainError error = DomainError.Create(Any.ErrorCode(), Any.DiagnosticMessage(), innerErrors).WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.InnerErrors).IsEmpty(); @@ -239,7 +241,7 @@ public void ACollectionMadeOnlyOfNullInnerErrorsYieldsAnEmptyInnerErrorsList() { [Fact(DisplayName = "The string representation combines the diagnostic message and the code.")] public void TheStringRepresentationCombinesTheDiagnosticMessageAndTheCode() { // Exercise - DomainError error = DomainError.Create(ErrorCode.Unspecified, "boom").WithPublicMessage("short"); + DomainError error = DomainError.Create(ErrorCode.Unspecified, "boom").WithPublicMessage(Any.ShortMessage()); // Verify Check.That(error.ToString()).IsEqualTo("boom (#UNSPECIFIED)"); diff --git a/FirstClassErrors.UnitTests/ErrorDescriptionTests.cs b/FirstClassErrors.UnitTests/ErrorDescriptionTests.cs index c90a5d4..2b96b64 100644 --- a/FirstClassErrors.UnitTests/ErrorDescriptionTests.cs +++ b/FirstClassErrors.UnitTests/ErrorDescriptionTests.cs @@ -1,5 +1,7 @@ #region Usings declarations +using FirstClassErrors.Testing; + using JetBrains.Annotations; using NFluent; @@ -14,7 +16,7 @@ public sealed class ErrorDescriptionTests { [Fact(DisplayName = "An error description cannot be created with a null short message.")] public void AnErrorDescriptionCannotBeCreatedWithANullShortMessage() { // Exercise & verify - Check.ThatCode(() => new ErrorDescription(null!, "diagnostic")) + Check.ThatCode(() => new ErrorDescription(null!, Any.DiagnosticMessage())) .Throws(); } @@ -24,14 +26,14 @@ public void AnErrorDescriptionCannotBeCreatedWithANullShortMessage() { [InlineData(" ")] public void AnErrorDescriptionCannotBeCreatedWithAnEmptyOrWhitespaceShortMessage(string value) { // Exercise & verify - Check.ThatCode(() => new ErrorDescription(value, "diagnostic")) + Check.ThatCode(() => new ErrorDescription(value, Any.DiagnosticMessage())) .Throws(); } [Fact(DisplayName = "An error description cannot be created with a null diagnostic message.")] public void AnErrorDescriptionCannotBeCreatedWithANullDiagnosticMessage() { // Exercise & verify - Check.ThatCode(() => new ErrorDescription("short", null!)) + Check.ThatCode(() => new ErrorDescription(Any.ShortMessage(), null!)) .Throws(); } @@ -41,14 +43,14 @@ public void AnErrorDescriptionCannotBeCreatedWithANullDiagnosticMessage() { [InlineData(" ")] public void AnErrorDescriptionCannotBeCreatedWithAnEmptyOrWhitespaceDiagnosticMessage(string value) { // Exercise & verify - Check.ThatCode(() => new ErrorDescription("short", value)) + Check.ThatCode(() => new ErrorDescription(Any.ShortMessage(), value)) .Throws(); } [Fact(DisplayName = "An error description trims the short message.")] public void AnErrorDescriptionTrimsTheShortMessage() { // Exercise - ErrorDescription description = new(" Short message ", "Diagnostic message"); + ErrorDescription description = new(" Short message ", Any.DiagnosticMessage()); // Verify Check.That(description.ShortMessage).IsEqualTo("Short message"); @@ -57,7 +59,7 @@ public void AnErrorDescriptionTrimsTheShortMessage() { [Fact(DisplayName = "An error description trims the diagnostic message.")] public void AnErrorDescriptionTrimsTheDiagnosticMessage() { // Exercise - ErrorDescription description = new("Short message", " Diagnostic message "); + ErrorDescription description = new(Any.ShortMessage(), " Diagnostic message "); // Verify Check.That(description.DiagnosticMessage).IsEqualTo("Diagnostic message"); @@ -66,7 +68,7 @@ public void AnErrorDescriptionTrimsTheDiagnosticMessage() { [Fact(DisplayName = "An error description sets detailed message to null when not provided.")] public void AnErrorDescriptionSetsDetailedMessageToNullWhenNotProvided() { // Exercise - ErrorDescription description = new("Short message", "Diagnostic message"); + ErrorDescription description = new(Any.ShortMessage(), Any.DiagnosticMessage()); // Verify Check.That(description.DetailedMessage).IsNull(); @@ -78,7 +80,7 @@ public void AnErrorDescriptionSetsDetailedMessageToNullWhenNotProvided() { [InlineData(" ")] public void AnErrorDescriptionSetsDetailedMessageToNullWhenItIsEmptyOrWhitespace(string value) { // Exercise - ErrorDescription description = new("Short message", "Diagnostic message", value); + ErrorDescription description = new(Any.ShortMessage(), Any.DiagnosticMessage(), value); // Verify Check.That(description.DetailedMessage).IsNull(); @@ -87,7 +89,7 @@ public void AnErrorDescriptionSetsDetailedMessageToNullWhenItIsEmptyOrWhitespace [Fact(DisplayName = "An error description trims the detailed message when provided.")] public void AnErrorDescriptionTrimsTheDetailedMessageWhenProvided() { // Exercise - ErrorDescription description = new("Short message", "Diagnostic message", " Detailed "); + ErrorDescription description = new(Any.ShortMessage(), Any.DiagnosticMessage(), " Detailed "); // Verify Check.That(description.DetailedMessage).IsEqualTo("Detailed"); diff --git a/FirstClassErrors.UnitTests/ErrorDiagnosticTests.cs b/FirstClassErrors.UnitTests/ErrorDiagnosticTests.cs index 887cb73..87d6afb 100644 --- a/FirstClassErrors.UnitTests/ErrorDiagnosticTests.cs +++ b/FirstClassErrors.UnitTests/ErrorDiagnosticTests.cs @@ -1,5 +1,7 @@ #region Usings declarations +using FirstClassErrors.Testing; + using JetBrains.Annotations; using NFluent; @@ -14,14 +16,14 @@ public sealed class ErrorDiagnosticTests { [Fact(DisplayName = "An error diagnostic cannot be created with a null cause.")] public void AnErrorDiagnosticCannotBeCreatedWithANullCause() { // Exercise & verify - Check.ThatCode(() => new ErrorDiagnostic(null!, ErrorOrigin.Internal, StringFactory.AnyAnalysisLead())) + Check.ThatCode(() => new ErrorDiagnostic(null!, Any.ErrorOrigin(), StringFactory.AnyAnalysisLead())) .Throws(); } [Fact(DisplayName = "An error diagnostic cannot be created with a null analysis lead.")] public void AnErrorDiagnosticCannotBeCreatedWithANullAnalysisLead() { // Exercise & verify - Check.ThatCode(() => new ErrorDiagnostic(StringFactory.AnyCause(), ErrorOrigin.External, null!)) + Check.ThatCode(() => new ErrorDiagnostic(StringFactory.AnyCause(), Any.ErrorOrigin(), null!)) .Throws(); } @@ -31,7 +33,7 @@ public void AnErrorDiagnosticCannotBeCreatedWithANullAnalysisLead() { [InlineData(" ")] public void AnErrorDiagnosticCannotBeCreatedWithAnEmptyOrWhitespaceCause(string value) { // Exercise & verify - Check.ThatCode(() => new ErrorDiagnostic(value, ErrorOrigin.Internal, StringFactory.AnyAnalysisLead())) + Check.ThatCode(() => new ErrorDiagnostic(value, Any.ErrorOrigin(), StringFactory.AnyAnalysisLead())) .Throws(); } @@ -41,14 +43,14 @@ public void AnErrorDiagnosticCannotBeCreatedWithAnEmptyOrWhitespaceCause(string [InlineData(" ")] public void AnErrorDiagnosticCannotBeCreatedWithAnEmptyOrWhitespaceAnalysisLead(string value) { // Exercise & verify - Check.ThatCode(() => new ErrorDiagnostic(StringFactory.AnyCause(), ErrorOrigin.Internal, value)) + Check.ThatCode(() => new ErrorDiagnostic(StringFactory.AnyCause(), Any.ErrorOrigin(), value)) .Throws(); } [Fact(DisplayName = "An error diagnostic normalizes the cause by removing surrounding whitespace.")] public void AnErrorDiagnosticTrimsTheCause() { // Exercise - ErrorDiagnostic diagnostic = new(" Invalid input. ", ErrorOrigin.External, StringFactory.AnyAnalysisLead()); + ErrorDiagnostic diagnostic = new(" Invalid input. ", Any.ErrorOrigin(), StringFactory.AnyAnalysisLead()); // Verify Check.That(diagnostic.PossibleCause).IsEqualTo("Invalid input."); @@ -57,7 +59,7 @@ public void AnErrorDiagnosticTrimsTheCause() { [Fact(DisplayName = "An error diagnostic normalizes the analysis lead by removing surrounding whitespace.")] public void AnErrorDiagnosticTrimsTheAnalysisLead() { // Exercise - ErrorDiagnostic diagnostic = new(StringFactory.AnyCause(), ErrorOrigin.Internal, " Inspect payload "); + ErrorDiagnostic diagnostic = new(StringFactory.AnyCause(), Any.ErrorOrigin(), " Inspect payload "); // Verify Check.That(diagnostic.AnalysisHint).IsEqualTo("Inspect payload"); diff --git a/FirstClassErrors.UnitTests/ErrorDocumentationBuilderTests.cs b/FirstClassErrors.UnitTests/ErrorDocumentationBuilderTests.cs index 606f213..0545aa8 100644 --- a/FirstClassErrors.UnitTests/ErrorDocumentationBuilderTests.cs +++ b/FirstClassErrors.UnitTests/ErrorDocumentationBuilderTests.cs @@ -2,6 +2,8 @@ using System.Diagnostics.CodeAnalysis; +using FirstClassErrors.Testing; + using JetBrains.Annotations; using NFluent; @@ -56,7 +58,7 @@ public void AnErrorDocumentationTitleCannotBeEmptyOrWhitespace(string title) { public void AnErrorDocumentationTitleIsTrimmed() { // Setup ErrorDocumentationBuilder builder = new(); - ErrorCode anyErrorCode = ErrorCodeFactory.CreateAny(); + ErrorCode anyErrorCode = Any.ErrorCode(); string anyErrorLongMessage = StringFactory.AnyErrorLongMessage(); // Exercise @@ -85,7 +87,7 @@ public void AnErrorDocumentationDescriptionCannotBeNull() { public void AnErrorDocumentationDescriptionIsTrimmed() { // Setup ErrorDocumentationBuilder builder = new(); - ErrorCode anyErrorCode = ErrorCodeFactory.CreateAny(); + ErrorCode anyErrorCode = Any.ErrorCode(); string anyTitle = StringFactory.AnyTitle(); string anyErrorLongMessage = StringFactory.AnyErrorLongMessage(); @@ -115,7 +117,7 @@ public void AnErrorDocumentationRuleCannotBeNull() { public void AnErrorDocumentationRuleIsTrimmed() { // Setup ErrorDocumentationBuilder builder = new(); - ErrorCode anyErrorCode = ErrorCodeFactory.CreateAny(); + ErrorCode anyErrorCode = Any.ErrorCode(); string anyTitle = StringFactory.AnyTitle(); string anyExplanation = StringFactory.AnyExplanation(); string anyErrorLongMessage = StringFactory.AnyErrorLongMessage(); @@ -136,7 +138,7 @@ public void AnErrorDocumentationRuleIsTrimmed() { public void AnErrorDocumentationCanBeBuiltWithoutARule() { // Setup ErrorDocumentationBuilder builder = new(); - ErrorCode anyErrorCode = ErrorCodeFactory.CreateAny(); + ErrorCode anyErrorCode = Any.ErrorCode(); string anyTitle = StringFactory.AnyTitle(); string anyExplanation = StringFactory.AnyExplanation(); string anyErrorLongMessage = StringFactory.AnyErrorLongMessage(); @@ -191,8 +193,8 @@ public void AnErrorDocumentationBuilderRejectsANullExampleFactoryAmongTheProvide // Setup ErrorDocumentationBuilder builder = new(); - ErrorCode code = ErrorCode.Create("ANY_CODE"); - Func valid = () => ErrorFactory.Domain(code, "boom"); + ErrorCode code = Any.ErrorCode(); + Func valid = () => ErrorFactory.Domain(code, Any.DiagnosticMessage()); // Exercise & verify Check.ThatCode(() => builder.WithExamples(valid, null!)) @@ -232,8 +234,8 @@ public void AnErrorDocumentationBuilderRejectsInconsistentErrorCodesAcrossExampl ErrorCode codeA = ErrorCode.Create("CODE_A"); ErrorCode codeB = ErrorCode.Create("CODE_B"); - Func first = () => ErrorFactory.Domain(codeA, "m1"); - Func second = () => ErrorFactory.Domain(codeB, "m2"); + Func first = () => ErrorFactory.Domain(codeA, Any.DiagnosticMessage()); + Func second = () => ErrorFactory.Domain(codeB, Any.DiagnosticMessage()); // Exercise & verify Check.ThatCode(() => builder.WithExamples(first, second)) @@ -270,8 +272,8 @@ public void AnErrorDocumentationBuilderIncludesTheProvidedDiagnostics() { ErrorDiagnostic first = new("cause-1", ErrorOrigin.External, "lead-1"); ErrorDiagnostic second = new("cause-2", ErrorOrigin.Internal, "lead-2"); - ErrorCode code = ErrorCode.Create("ANY_CODE"); - Func example = () => ErrorFactory.Domain(code, "boom"); + ErrorCode code = Any.ErrorCode(); + Func example = () => ErrorFactory.Domain(code, Any.DiagnosticMessage()); // Exercise ErrorDocumentation doc = builder @@ -296,8 +298,8 @@ public void AnErrorDocumentationBuilderIncludesDiagnosticsAddedIncrementally() { // Setup ErrorDocumentationBuilder builder = new(); - ErrorCode code = ErrorCode.Create("ANY_CODE"); - Func example = () => ErrorFactory.Domain(code, "boom"); + ErrorCode code = Any.ErrorCode(); + Func example = () => ErrorFactory.Domain(code, Any.DiagnosticMessage()); // Exercise ErrorDocumentation doc = builder @@ -316,23 +318,23 @@ public void AnErrorDocumentationBuilderAggregatesContextEntriesByKeyName() { ErrorContextKey userId = ErrorContextKey.Create("UserId", "User identifier."); ErrorContextKey correlationId = ErrorContextKey.Create("CorrelationId", "Correlation identifier."); - ErrorCode code = ErrorCode.Create("ANY_CODE"); + ErrorCode code = Any.ErrorCode(); Func ex1 = () => DomainError.Create( code, - "m1", + Any.DiagnosticMessage(), ctx => { ctx.Add(userId, "u-1"); ctx.Add(correlationId, "c-1"); - }).WithPublicMessage("m1"); + }).WithPublicMessage(Any.ShortMessage()); Func ex2 = () => DomainError.Create( code, - "m2", + Any.DiagnosticMessage(), ctx => { ctx.Add(userId, "u-2"); ctx.Add(correlationId, "c-1"); - }).WithPublicMessage("m2"); + }).WithPublicMessage(Any.ShortMessage()); // Exercise ErrorDocumentation doc = new ErrorDocumentationBuilder() @@ -357,17 +359,17 @@ public void AnErrorDocumentationBuilderAggregatesContextEntriesByKeyName() { public void AnErrorDocumentationBuilderExcludesNullContextExampleValues() { // Setup ErrorContextKey optionalInfo = ErrorContextKey.Create("OptionalInfo", "Optional info."); - ErrorCode code = ErrorCode.Create("ANY_CODE"); + ErrorCode code = Any.ErrorCode(); Func ex1 = () => DomainError.Create( code, - "m1", - ctx => ctx.Add(optionalInfo, null)).WithPublicMessage("m1"); + Any.DiagnosticMessage(), + ctx => ctx.Add(optionalInfo, null)).WithPublicMessage(Any.ShortMessage()); Func ex2 = () => DomainError.Create( code, - "m2", - ctx => ctx.Add(optionalInfo, "x")).WithPublicMessage("m2"); + Any.DiagnosticMessage(), + ctx => ctx.Add(optionalInfo, "x")).WithPublicMessage(Any.ShortMessage()); // Exercise ErrorDocumentation doc = new ErrorDocumentationBuilder() @@ -384,17 +386,17 @@ public void AnErrorDocumentationBuilderDeduplicatesContextExampleValuesByTheirRe // apply to the rendered string, not to object identity — otherwise reference-unequal values that look identical // in the documentation would appear twice. ErrorContextKey