From 10e3a1aa944a5056cadda169d11970ecfbd74257 Mon Sep 17 00:00:00 2001 From: glhays Date: Thu, 12 Jun 2025 18:05:27 -0700 Subject: [PATCH 1/4] ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExceptionOccursAndLogItAsync -> FAIL * Closes: #310 --- .../RepositoryServiceTests.Exceptions.Add.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs index 8bbddf81..ba7a5f63 100644 --- a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs +++ b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs @@ -177,6 +177,62 @@ await Assert.ThrowsAsync( this.storageBrokerMock.VerifyNoOtherCalls(); } + [Fact] + public async Task ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExceptionOccursAndLogItAsync() + { + // given + Repository someRepository = CreateRandomRepository(); + string someMessage = GetRandomString(); + + var foreignKeyConstraintConflictException = + new ForeignKeyConstraintConflictException(someMessage); + + var failedStorageRepositoryException = + new FailedStorageRepositoryException( + message: "Failed storage repository error occurred, contact support.", + innerException: foreignKeyConstraintConflictException); + + var expectedRepositoryDependencyValidationException = + new RepositoryDependencyValidationException( + message: "Repository dependency validation error occurred, fix errors and try again.", + innerException: failedStorageRepositoryException, + data: failedStorageRepositoryException.Data); + + this.dateTimeBrokerMock.Setup(broker => + broker.GetCurrentDateTimeOffsetAsync()) + .ThrowsAsync(foreignKeyConstraintConflictException); + + // when + ValueTask addRepositoryTask = + this.repositoryService.AddRepositoryAsync( + someRepository); + + RepositoryDependencyValidationException actualRepositoryDependencyValidationException = + await Assert.ThrowsAsync( + testCode: addRepositoryTask.AsTask); + + // then + actualRepositoryDependencyValidationException.Should().BeEquivalentTo( + expectedRepositoryDependencyValidationException); + + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffsetAsync(), + Times.Once); + + this.loggingBrokerMock.Verify(broker => + broker.LogErrorAsync(It.Is(SameExceptionAs( + expectedRepositoryDependencyValidationException))), + Times.Once); + + this.storageBrokerMock.Verify(broker => + broker.InsertRepositoryAsync(It.IsAny()), + Times.Never); + + this.dateTimeBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); + } + [Fact] public async Task ShouldThrowServiceExceptionOnAddIfServiceErrorOccurredAndLogItAsync() { From 05094f7e2a822daa69616e795bc9b684d34af243 Mon Sep 17 00:00:00 2001 From: Greg Hays Date: Fri, 13 Jun 2025 15:57:14 -0700 Subject: [PATCH 2/4] ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExceptionOccursAndLogItAsync -> FAIL --- .../RepositoryServiceTests.Exceptions.Add.cs | 19 +++++++++---------- .../InvalidRepositoryReferenceException.cs | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs diff --git a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs index ba7a5f63..1222de62 100644 --- a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs +++ b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs @@ -187,16 +187,16 @@ public async Task ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExcep var foreignKeyConstraintConflictException = new ForeignKeyConstraintConflictException(someMessage); - var failedStorageRepositoryException = - new FailedStorageRepositoryException( - message: "Failed storage repository error occurred, contact support.", + var invalidRepositoryReferenceException = + new InvalidRepositoryReferenceException( + message: "Invalid repository reference error occurred, ", innerException: foreignKeyConstraintConflictException); var expectedRepositoryDependencyValidationException = new RepositoryDependencyValidationException( message: "Repository dependency validation error occurred, fix errors and try again.", - innerException: failedStorageRepositoryException, - data: failedStorageRepositoryException.Data); + innerException: invalidRepositoryReferenceException, + data: invalidRepositoryReferenceException.Data); this.dateTimeBrokerMock.Setup(broker => broker.GetCurrentDateTimeOffsetAsync()) @@ -204,16 +204,15 @@ public async Task ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExcep // when ValueTask addRepositoryTask = - this.repositoryService.AddRepositoryAsync( - someRepository); + this.repositoryService.AddRepositoryAsync(someRepository); RepositoryDependencyValidationException actualRepositoryDependencyValidationException = await Assert.ThrowsAsync( - testCode: addRepositoryTask.AsTask); + addRepositoryTask.AsTask); // then - actualRepositoryDependencyValidationException.Should().BeEquivalentTo( - expectedRepositoryDependencyValidationException); + actualRepositoryDependencyValidationException.Should() + .BeEquivalentTo(expectedRepositoryDependencyValidationException); this.dateTimeBrokerMock.Verify(broker => broker.GetCurrentDateTimeOffsetAsync(), diff --git a/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs b/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs new file mode 100644 index 00000000..dc016545 --- /dev/null +++ b/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs @@ -0,0 +1,16 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using Xeptions; + +namespace GitFyle.Core.Api.Models.Foundations.Repositories.Exceptions +{ + public class InvalidRepositoryReferenceException : Xeption + { + public InvalidRepositoryReferenceException(string message, Exception innerException) + : base(message, innerException) + { } + } +} \ No newline at end of file From 1e8d5a5c61a9390f54ecaf3a05af1fa83dd1f244 Mon Sep 17 00:00:00 2001 From: Greg Hays Date: Fri, 13 Jun 2025 16:17:46 -0700 Subject: [PATCH 3/4] ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExceptionOccursAndLogItAsync -> PASS --- .../RepositoryServiceTests.Exceptions.Add.cs | 7 ++++--- .../Exceptions/InvalidRepositoryReferenceException.cs | 5 +++-- .../Repositories/RepositoryService.Exceptions.cs | 10 ++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs index 1222de62..fa645600 100644 --- a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs +++ b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Add.cs @@ -189,12 +189,13 @@ public async Task ShouldThrowDependencyValidationExceptionOnAddIfForeignKeyExcep var invalidRepositoryReferenceException = new InvalidRepositoryReferenceException( - message: "Invalid repository reference error occurred, ", - innerException: foreignKeyConstraintConflictException); + message: "Invalid repository reference error occurred.", + innerException: foreignKeyConstraintConflictException, + data: foreignKeyConstraintConflictException.Data); var expectedRepositoryDependencyValidationException = new RepositoryDependencyValidationException( - message: "Repository dependency validation error occurred, fix errors and try again.", + message: "Repository validation error occurred, fix errors and try again.", innerException: invalidRepositoryReferenceException, data: invalidRepositoryReferenceException.Data); diff --git a/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs b/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs index dc016545..1777f435 100644 --- a/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs +++ b/GitFyle.Core.Api/Models/Foundations/Repositories/Exceptions/InvalidRepositoryReferenceException.cs @@ -3,14 +3,15 @@ // ---------------------------------------------------------------------------------- using System; +using System.Collections; using Xeptions; namespace GitFyle.Core.Api.Models.Foundations.Repositories.Exceptions { public class InvalidRepositoryReferenceException : Xeption { - public InvalidRepositoryReferenceException(string message, Exception innerException) - : base(message, innerException) + public InvalidRepositoryReferenceException(string message, Exception innerException, IDictionary data) + : base(message, innerException, data) { } } } \ No newline at end of file diff --git a/GitFyle.Core.Api/Services/Foundations/Repositories/RepositoryService.Exceptions.cs b/GitFyle.Core.Api/Services/Foundations/Repositories/RepositoryService.Exceptions.cs index 145e9472..e469983b 100644 --- a/GitFyle.Core.Api/Services/Foundations/Repositories/RepositoryService.Exceptions.cs +++ b/GitFyle.Core.Api/Services/Foundations/Repositories/RepositoryService.Exceptions.cs @@ -55,6 +55,16 @@ private async ValueTask TryCatch(ReturningRepositoryFunction returni throw await CreateAndLogDependencyValidationExceptionAsync(alreadyExistsRepositoryException); } + catch (ForeignKeyConstraintConflictException foreignKeyConstraintConflictException) + { + var invalidRepositoryReferenceException = + new InvalidRepositoryReferenceException( + message: "Invalid repository reference error occurred.", + innerException: foreignKeyConstraintConflictException, + data: foreignKeyConstraintConflictException.Data); + + throw await CreateAndLogDependencyValidationExceptionAsync(invalidRepositoryReferenceException); + } catch (DbUpdateConcurrencyException dbUpdateConcurrencyException) { var concurrencyGemException = From 574c5936b5537b9fc64ea066620d78b30407e073 Mon Sep 17 00:00:00 2001 From: Greg Hays Date: Fri, 13 Jun 2025 16:39:05 -0700 Subject: [PATCH 4/4] ShouldThrowDependencyValidationExceptionOnModifyIfForeignKeyErrorOccursAndLogItAsync -> PASS --- ...epositoryServiceTests.Exceptions.Modify.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Modify.cs b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Modify.cs index 39396c07..4b51cd98 100644 --- a/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Modify.cs +++ b/GitFyle.Core.Api.Tests.Unit/Services/Foundations/Repositories/RepositoryServiceTests.Exceptions.Modify.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; +using EFxceptions.Models.Exceptions; using FluentAssertions; using GitFyle.Core.Api.Models.Foundations.Repositories; using GitFyle.Core.Api.Models.Foundations.Repositories.Exceptions; @@ -189,6 +190,63 @@ await Assert.ThrowsAsync( this.storageBrokerMock.VerifyNoOtherCalls(); } + [Fact] + public async Task ShouldThrowDependencyValidationExceptionOnModifyIfForeignKeyErrorOccursAndLogItAsync() + { + // given + Repository someRepository = CreateRandomRepository(); + string someMessage = GetRandomString(); + string exceptionMessage = someMessage; + + var foreignKeyConstraintConflictException = + new ForeignKeyConstraintConflictException(exceptionMessage); + + var invalidRepositoryReferenceException = + new InvalidRepositoryReferenceException( + message: "Invalid repository reference error occurred.", + innerException: foreignKeyConstraintConflictException, + data: foreignKeyConstraintConflictException.Data); + + var expectedRepositoryDependencyValidationException = + new RepositoryDependencyValidationException( + message: "Repository validation error occurred, fix errors and try again.", + innerException: invalidRepositoryReferenceException, + data: invalidRepositoryReferenceException.Data); + + this.dateTimeBrokerMock.Setup(broker => + broker.GetCurrentDateTimeOffsetAsync()) + .ThrowsAsync(foreignKeyConstraintConflictException); + + // when + ValueTask modifyRepositoryTask = + this.repositoryService.ModifyRepositoryAsync(someRepository); + + RepositoryDependencyValidationException actualRepositoryDependencyValidationException = + await Assert.ThrowsAsync( + modifyRepositoryTask.AsTask); + + // then + actualRepositoryDependencyValidationException.Should() + .BeEquivalentTo(expectedRepositoryDependencyValidationException); + + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffsetAsync(), + Times.Once); + + this.loggingBrokerMock.Verify(broker => + broker.LogErrorAsync(It.Is(SameExceptionAs( + expectedRepositoryDependencyValidationException))), + Times.Once); + + this.storageBrokerMock.Verify(broker => + broker.InsertRepositoryAsync(It.IsAny()), + Times.Never); + + this.dateTimeBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); + } + [Fact] public async Task ShouldThrowServiceExceptionOnModifyIfServiceErrorOccursAndLogItAsync() {