From 11c14fb62e44f379adadeb10b49bba9c810f1880 Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 13:31:08 +0500 Subject: [PATCH 1/8] FOUNDATIONS: DateTimeBroker Initialize Servise & Unit Test --- UsefulTime.Api/Brokers/DateTimes/IDateTimeBroker.cs | 2 +- .../Foundations/VedioMetadatas/VideoMetadataService.cs | 9 ++++++++- .../VideoMetadatas/VideoMetadataServiceTest.cs | 8 ++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/UsefulTime.Api/Brokers/DateTimes/IDateTimeBroker.cs b/UsefulTime.Api/Brokers/DateTimes/IDateTimeBroker.cs index c57ed04..6b0c3f6 100644 --- a/UsefulTime.Api/Brokers/DateTimes/IDateTimeBroker.cs +++ b/UsefulTime.Api/Brokers/DateTimes/IDateTimeBroker.cs @@ -3,7 +3,7 @@ //Free To Use To Find Comfort and Pease //================================================= namespace UsefulTime.Api.Brokers.DateTimes -{ +{ public interface IDateTimeBroker { DateTimeOffset GetCurrentDateTimeOffset(); diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs index 65cf6aa..494a691 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs @@ -2,6 +2,7 @@ //Copyright (c) Coalition of Good-Hearted Engineers //Free To Use To Find Comfort and Pease //================================================= +using UsefulTime.Api.Brokers.DateTimes; using UsefulTime.Api.Brokers.Loggings; using UsefulTime.Api.Brokers.Storages; using UsefulTime.Api.Models.VideoMetadatas; @@ -12,12 +13,18 @@ public partial class VideoMetadataService : IVideoMetadataService { private readonly IStorageBroker storageBroker; private readonly ILoggingBroker loggingBroker; + private readonly IDateTimeBroker dateTimeBroker; - public VideoMetadataService(IStorageBroker storageBroker, ILoggingBroker loggingBroker) + public VideoMetadataService( + IStorageBroker storageBroker, + ILoggingBroker loggingBroker, + IDateTimeBroker dateTimeBroker) { this.storageBroker = storageBroker; this.loggingBroker = loggingBroker; + this.dateTimeBroker = dateTimeBroker; } + public ValueTask AddVideoMetadataAsync(VideoMetadata videoMetadata) => TryCatch(async () => { diff --git a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs index fcbc34e..0c1025c 100644 --- a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs +++ b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs @@ -8,6 +8,7 @@ using System.Linq.Expressions; using System.Runtime.Serialization; using Tynamix.ObjectFiller; +using UsefulTime.Api.Brokers.DateTimes; using UsefulTime.Api.Brokers.Loggings; using UsefulTime.Api.Brokers.Storages; using UsefulTime.Api.Models.VideoMetadatas; @@ -20,16 +21,19 @@ public partial class VideoMetadataServiceTest { private readonly Mock storageBrokerMock; private readonly Mock loggingBrokerMock; + private readonly Mock dateTimeBrokerMock; private readonly IVideoMetadataService videoMetadataService; public VideoMetadataServiceTest() { this.storageBrokerMock = new Mock(); this.loggingBrokerMock = new Mock(); + this.dateTimeBrokerMock= new Mock(); this.videoMetadataService = new VideoMetadataService (storageBroker: this.storageBrokerMock.Object, - loggingBroker: loggingBrokerMock.Object); + loggingBroker: loggingBrokerMock.Object, + dateTimeBroker:this.dateTimeBrokerMock.Object); } private Expression> SameExceptionAs(Xeption expectedException) => @@ -40,7 +44,7 @@ private static VideoMetadata CreateRandomVideoMetadata() => public static DateTimeOffset GetRandomDateTimeOffset() => new DateTimeRange(earliestDate: new DateTime()).GetValue(); - private static Filler CreateVideoMetadataFiller(DateTimeOffset date) + private static Filler CreateVideoMetadataFiller(DateTimeOffset date) { var filler = new Filler(); From 088c7f21e29953142d8754c1299be7c99949e6ef Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 13:33:31 +0500 Subject: [PATCH 2/8] CODE RUB: AddTransient DateTimeBroker --- UsefulTime.Api/Program.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UsefulTime.Api/Program.cs b/UsefulTime.Api/Program.cs index 1f3e04c..71cb4e5 100644 --- a/UsefulTime.Api/Program.cs +++ b/UsefulTime.Api/Program.cs @@ -2,6 +2,7 @@ //Copyright (c) Coalition of Good-Hearted Engineers //Free To Use To Find Comfort and Pease //================================================= +using UsefulTime.Api.Brokers.DateTimes; using UsefulTime.Api.Brokers.Loggings; using UsefulTime.Api.Brokers.Storages; using UsefulTime.Api.Services.Foundations.VideoMetadatas; @@ -18,6 +19,7 @@ private static void Main(string[] args) builder.Services.AddSwaggerGen(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(); var app = builder.Build(); From 7cf47a67f823c0fb4cff26b100a9017c1f41fd7d Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 13:38:39 +0500 Subject: [PATCH 3/8] ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync->FAIL --- .../LockedVideoMetadataException.cs | 15 ++++++ ...VideoMetadataServiceTest.Exceptions.Add.cs | 46 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 UsefulTime.Api/Models/VideoMetadatas/Exceptions/LockedVideoMetadataException.cs diff --git a/UsefulTime.Api/Models/VideoMetadatas/Exceptions/LockedVideoMetadataException.cs b/UsefulTime.Api/Models/VideoMetadatas/Exceptions/LockedVideoMetadataException.cs new file mode 100644 index 0000000..e58135f --- /dev/null +++ b/UsefulTime.Api/Models/VideoMetadatas/Exceptions/LockedVideoMetadataException.cs @@ -0,0 +1,15 @@ +//================================================= +//Copyright (c) Coalition of Good-Hearted Engineers +//Free To Use To Find Comfort and Pease +//================================================= +using Xeptions; + +namespace UsefulTime.Api.Models.VideoMetadatas.Exceptions +{ + public class LockedVideoMetadataException:Xeption + { + public LockedVideoMetadataException(string message, Exception innerException) + : base(message, innerException) + { } + } +} diff --git a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs index 7249bda..f5d168f 100644 --- a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs +++ b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs @@ -5,6 +5,7 @@ using EFxceptions.Models.Exceptions; using FluentAssertions; using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; using Moq; using UsefulTime.Api.Models.VideoMetadatas; using UsefulTime.Api.Models.VideoMetadatas.Exceptions; @@ -102,5 +103,50 @@ public async Task ShouldThrowDependencyValidationOnAddIfDublicateKeyErrorOccursA this.storageBrokerMock.VerifyNoOtherCalls(); this.loggingBrokerMock.VerifyNoOtherCalls(); } + [Fact] + public async Task ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync() + { + //given + VideoMetadata someVideoMetadata = CreateRandomVideoMetadata(); + var dbUpdateConcurrencyException = new DbUpdateConcurrencyException(); + + var lockedVideoMetadataException = + new LockedVideoMetadataException("Video Metadata is locked, please try again.", + dbUpdateConcurrencyException); + + VideoMetadataDependencyValidationException expectedVideoMetadataDependencyValidationException = + new VideoMetadataDependencyValidationException( + "Video metadata dependency error occurred,fix the errors try again", + lockedVideoMetadataException); + + this.dateTimeBrokerMock.Setup(broker => + broker.GetCurrentDateTimeOffset()) + .Throws(dbUpdateConcurrencyException); + + //when + ValueTask addVideoMetadataTask = + this.videoMetadataService.AddVideoMetadataAsync(someVideoMetadata); + + var actualVideoMetadataDependencyValidationException = + await Assert.ThrowsAsync(addVideoMetadataTask.AsTask); + + //then + actualVideoMetadataDependencyValidationException.Should() + .BeEquivalentTo(expectedVideoMetadataDependencyValidationException); + + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffset(), Times.Once); + + this.loggingBrokerMock.Verify(broker => + broker.LogError(It.Is(SameExceptionAs(expectedVideoMetadataDependencyValidationException))), + Times.Once); + + this.storageBrokerMock.Verify(broker => + broker.InsertVideoMetadataAsync(someVideoMetadata), Times.Never); + + this.dateTimeBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } } } From ddab817d463bcea4562100b1bf8243b180521f9a Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 13:46:03 +0500 Subject: [PATCH 4/8] ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync->PASS --- .../VideoMetadataService.Exceptions.cs | 19 +++++++++++ .../VideoMetadataService.Validations.cs | 33 +++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs index 843a057..9e5d52b 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs @@ -4,6 +4,7 @@ //================================================= using EFxceptions.Models.Exceptions; using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; using UsefulTime.Api.Models.VideoMetadatas; using UsefulTime.Api.Models.VideoMetadatas.Exceptions; using Xeptions; @@ -43,6 +44,14 @@ private async ValueTask TryCatch(ReturningVideoMetadataFunction r innerException: duplicateKeyException); throw CreateAndDependencyValidationException(alreadyExistVideoMetadataException); } + catch (DbUpdateConcurrencyException dbUpdateConcurrencyException) + { + LockedVideoMetadataException lockedVideoMetadataException = new LockedVideoMetadataException( + "Video Metadata is locked, please try again.", + dbUpdateConcurrencyException); + + throw CreateAndLogDependencyValidationException(lockedVideoMetadataException); + } catch (Exception exception) { var failedVideoMetadataServiceException = @@ -86,5 +95,15 @@ public VideoMetadataDependencyValidationException CreateAndDependencyValidationE this.loggingBroker.LogError(videoMetadataDependencyValidationException); return videoMetadataDependencyValidationException; } + private VideoMetadataDependencyValidationException CreateAndLogDependencyValidationException(Xeption exception) + { + var videoMetadataDependencyValidationException = new VideoMetadataDependencyValidationException( + "Video metadata dependency error occurred,fix the errors try again", + exception); + + this.loggingBroker.LogError(videoMetadataDependencyValidationException); + + return videoMetadataDependencyValidationException; + } } } diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs index 8434536..b7ba092 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs @@ -18,7 +18,16 @@ private void ValidatevideoMetadataOnAdd(VideoMetadata videoMetadata) (Rule: IsInvalid(videoMetadata.Title), Parameter: nameof(videoMetadata.Title)), (Rule: IsInvalid(videoMetadata.BlobPath), Parameter: nameof(videoMetadata.BlobPath)), (Rule: IsInvalid(videoMetadata.CreatedDate), Parameter: nameof(videoMetadata.CreatedDate)), - (Rule: IsInvalid(videoMetadata.UpdatedDate), Parameter: nameof(videoMetadata.UpdatedDate))); + (Rule: IsInvalid(videoMetadata.UpdatedDate), Parameter: nameof(videoMetadata.UpdatedDate)), + (Rule: IsInvalid(videoMetadata.UpdatedDate), Parameter: nameof(videoMetadata.UpdatedDate)), + (Rule: IsNotRecent(videoMetadata.CreatedDate), Parameter: nameof(videoMetadata.CreatedDate)), + + (Rule: IsNotSame( + firstDate: videoMetadata.CreatedDate, + secondDate: videoMetadata.UpdatedDate, + secondDateName: nameof(videoMetadata.UpdatedDate)), + + Parameter: nameof(videoMetadata.CreatedDate))); } private void ValidationVideoMetadataNotNull(VideoMetadata videoMetadata) { @@ -42,9 +51,29 @@ private void ValidationVideoMetadataNotNull(VideoMetadata videoMetadata) Condition = date == default, Message = "Data is required" }; + private static dynamic IsNotSame( + DateTimeOffset firstDate, + DateTimeOffset secondDate, + string secondDateName) => new + { + Condition = firstDate != secondDate, + Message = $"Date is not same as {secondDateName}" + }; + private dynamic IsNotRecent(DateTimeOffset date) => new + { + Condition = IsDateNotRecent(date), + Message = "Date is not recent" + }; + private bool IsDateNotRecent(DateTimeOffset date) + { + DateTimeOffset currentDateTime = this.dateTimeBroker.GetCurrentDateTimeOffset(); + TimeSpan timeDifference = currentDateTime.Subtract(date); + + return timeDifference.TotalSeconds is > 60 or < 0; + } private static void Validate(params (dynamic Rule, string Parameter)[] validations) { - var invalidVideoMetadataException = + var invalidVideoMetadataException = new InvalidVideoMetadataException(message: "Video metadata is invalid"); foreach ((dynamic rule, string parameter) in validations) From df3ecb86bd931371919508b7141d410b84e9db8a Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 16:43:06 +0500 Subject: [PATCH 5/8] ShouldThrowDependencyExceptionOnAddIfDbUpdateErrorOccursAndLogItAsync->PASS --- UsefulTime.Api/Program.cs | 2 +- .../VideoMetadataService.Exceptions.cs | 24 ++-- .../VideoMetadataService.Validations.cs | 26 ++-- .../VedioMetadatas/VideoMetadataService.cs | 2 +- ...VideoMetadataServiceTest.Exceptions.Add.cs | 123 +++++++++--------- .../VideoMetadataServiceTest.Logic.Add.cs | 8 +- .../VideoMetadataServiceTest.cs | 21 +-- 7 files changed, 103 insertions(+), 103 deletions(-) diff --git a/UsefulTime.Api/Program.cs b/UsefulTime.Api/Program.cs index 71cb4e5..dc86ac2 100644 --- a/UsefulTime.Api/Program.cs +++ b/UsefulTime.Api/Program.cs @@ -19,7 +19,7 @@ private static void Main(string[] args) builder.Services.AddSwaggerGen(); builder.Services.AddTransient(); builder.Services.AddTransient(); - builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(); var app = builder.Build(); diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs index 9e5d52b..f7c364b 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs @@ -44,13 +44,13 @@ private async ValueTask TryCatch(ReturningVideoMetadataFunction r innerException: duplicateKeyException); throw CreateAndDependencyValidationException(alreadyExistVideoMetadataException); } - catch (DbUpdateConcurrencyException dbUpdateConcurrencyException) + catch (DbUpdateException databaseUpdateException) { - LockedVideoMetadataException lockedVideoMetadataException = new LockedVideoMetadataException( - "Video Metadata is locked, please try again.", - dbUpdateConcurrencyException); + var failedVideoMetadataStorageException = new FailedVideoMetadataStorageException( + message: "Failed video metadata error occured, contact support", + innerException: databaseUpdateException); - throw CreateAndLogDependencyValidationException(lockedVideoMetadataException); + throw CreateAndLogDependencyException(failedVideoMetadataStorageException); } catch (Exception exception) { @@ -90,20 +90,20 @@ public VideoMetadataDependencyValidationException CreateAndDependencyValidationE { var videoMetadataDependencyValidationException = new VideoMetadataDependencyValidationException( - message: "Video metadata dependency error occurred,fix the errors try again", + message: "Video metadata Dependency validation error occured,fix the errors and try again", innerException:exception ); this.loggingBroker.LogError(videoMetadataDependencyValidationException); return videoMetadataDependencyValidationException; } - private VideoMetadataDependencyValidationException CreateAndLogDependencyValidationException(Xeption exception) + private Exception CreateAndLogDependencyException(Xeption exception) { - var videoMetadataDependencyValidationException = new VideoMetadataDependencyValidationException( - "Video metadata dependency error occurred,fix the errors try again", - exception); + var videoMetadataDependencyException = new VideoMetadataDependencyException( + message: "Video metadata dependency error occured, fix the errors and try again", + innerException: exception); - this.loggingBroker.LogError(videoMetadataDependencyValidationException); + this.loggingBroker.LogError(videoMetadataDependencyException); - return videoMetadataDependencyValidationException; + return videoMetadataDependencyException; } } } diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs index b7ba092..a157929 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Validations.cs @@ -19,15 +19,13 @@ private void ValidatevideoMetadataOnAdd(VideoMetadata videoMetadata) (Rule: IsInvalid(videoMetadata.BlobPath), Parameter: nameof(videoMetadata.BlobPath)), (Rule: IsInvalid(videoMetadata.CreatedDate), Parameter: nameof(videoMetadata.CreatedDate)), (Rule: IsInvalid(videoMetadata.UpdatedDate), Parameter: nameof(videoMetadata.UpdatedDate)), - (Rule: IsInvalid(videoMetadata.UpdatedDate), Parameter: nameof(videoMetadata.UpdatedDate)), - (Rule: IsNotRecent(videoMetadata.CreatedDate), Parameter: nameof(videoMetadata.CreatedDate)), - + (Rule: IsNotRecent(videoMetadata.CreatedDate), Parameter: nameof(VideoMetadata.CreatedDate)), (Rule: IsNotSame( firstDate: videoMetadata.CreatedDate, secondDate: videoMetadata.UpdatedDate, - secondDateName: nameof(videoMetadata.UpdatedDate)), + secondDateName: nameof(VideoMetadata.UpdatedDate)), - Parameter: nameof(videoMetadata.CreatedDate))); + Parameter: nameof(VideoMetadata.CreatedDate))); } private void ValidationVideoMetadataNotNull(VideoMetadata videoMetadata) { @@ -52,18 +50,20 @@ private void ValidationVideoMetadataNotNull(VideoMetadata videoMetadata) Message = "Data is required" }; private static dynamic IsNotSame( - DateTimeOffset firstDate, - DateTimeOffset secondDate, - string secondDateName) => new - { - Condition = firstDate != secondDate, - Message = $"Date is not same as {secondDateName}" - }; + DateTimeOffset firstDate, + DateTimeOffset secondDate, + string secondDateName) => new + { + Condition = firstDate != secondDate, + Message = $"Date is not same as {secondDateName}" + }; + private dynamic IsNotRecent(DateTimeOffset date) => new { Condition = IsDateNotRecent(date), Message = "Date is not recent" }; + private bool IsDateNotRecent(DateTimeOffset date) { DateTimeOffset currentDateTime = this.dateTimeBroker.GetCurrentDateTimeOffset(); @@ -73,7 +73,7 @@ private bool IsDateNotRecent(DateTimeOffset date) } private static void Validate(params (dynamic Rule, string Parameter)[] validations) { - var invalidVideoMetadataException = + var invalidVideoMetadataException = new InvalidVideoMetadataException(message: "Video metadata is invalid"); foreach ((dynamic rule, string parameter) in validations) diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs index 494a691..fdebbde 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.cs @@ -16,7 +16,7 @@ public partial class VideoMetadataService : IVideoMetadataService private readonly IDateTimeBroker dateTimeBroker; public VideoMetadataService( - IStorageBroker storageBroker, + IStorageBroker storageBroker, ILoggingBroker loggingBroker, IDateTimeBroker dateTimeBroker) { diff --git a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs index f5d168f..dfa73de 100644 --- a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs +++ b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs @@ -15,134 +15,127 @@ namespace UsefulTime.Unit.Tests.Services.Foundations.VideoMetadatas public partial class VideoMetadataServiceTest { [Fact] - public async Task ShouldThrowCriticalDependencyExceptionOnAddIfSqlErrorOccursAndLogItAsync() + public async Task ShouldthrowCriticalDependencyExceptionOnAddIfSqlErrorOccursAndLogItAsync() { //given - VideoMetadata someVideoMetadata=CreateRandomVideoMetadata(); + VideoMetadata someVideoMetadata = CreateRandomVideoMetadata(); SqlException sqlException = GetSqlException(); - var failedVideoMetadataStorageException = + FailedVideoMetadataStorageException failedVideoMetadataStorageException = new FailedVideoMetadataStorageException( message: "Failed video metadata error occured, cotact support", innerException: sqlException); - var expectedVideoMetadataDependencyException = + VideoMetadataDependencyException expectedVideoMetadataDependencyException = new VideoMetadataDependencyException( - message:"Video metadata error occured, fix the errors and try again", + message: "Video metadata error occured, fix the errors and try again", innerException: failedVideoMetadataStorageException); - this.storageBrokerMock.Setup(broker => - broker.InsertVideoMetadataAsync(someVideoMetadata)) - .ThrowsAsync(sqlException); + this.dateTimeBrokerMock.Setup(broker => + broker.GetCurrentDateTimeOffset()).Throws(sqlException); //when - ValueTask addVideoMetadata= - this.videoMetadataService.AddVideoMetadataAsync(someVideoMetadata); + ValueTask addVideoMetadata = + this.videoMetadataService.AddVideoMetadataAsync(someVideoMetadata); VideoMetadataDependencyException actualVideoMetadataDependencyException = - await Assert.ThrowsAsync(addVideoMetadata.AsTask); + await Assert.ThrowsAsync(addVideoMetadata.AsTask); //then actualVideoMetadataDependencyException.Should() .BeEquivalentTo(expectedVideoMetadataDependencyException); - this.storageBrokerMock.Verify(broker => - broker.InsertVideoMetadataAsync(someVideoMetadata), Times.Once); + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffset(), Times.Once); this.loggingBrokerMock.Verify(broker => - broker.LogCritical(It.Is(SameExceptionAs( - expectedVideoMetadataDependencyException))), Times.Once); + broker.LogCritical(It.Is(SameExceptionAs( + actualVideoMetadataDependencyException))), + Times.Once); - this.storageBrokerMock.VerifyNoOtherCalls(); + this.dateTimeBrokerMock.VerifyNoOtherCalls(); this.loggingBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); } [Fact] - public async Task ShouldThrowDependencyValidationOnAddIfDublicateKeyErrorOccursAndLogItAsync() + public async Task ShouldThrowDependencyValidationExceptionOnAddIfDublicateKeyErrorOccursAndLogItAsync() { //given - VideoMetadata someVideoMetadata = CreateRandomVideoMetadata(); string someMessage = GetRandomString(); - - var duplicateKeyException = - new DuplicateKeyException(message:someMessage); - - var alreadyExistVideoMetadataException = - new AlreadyExistVideoMetadataException( - message: "VideoMetadata already exist", - innerException:duplicateKeyException); + VideoMetadata randomVideoMetadata = new VideoMetadata(); + var duplicateKeyException = new DuplicateKeyException(someMessage); + var alreadyExistsVideoMetadataException = new AlreadyExistVideoMetadataException( + message: "VideoMetadata already exist", + innerException: duplicateKeyException); var expectedVideoMetadataDependencyValidationException = new VideoMetadataDependencyValidationException( - message: "Video metadata dependency error occurred,fix the errors try again", - innerException:alreadyExistVideoMetadataException); + message: "Video metadata Dependency validation error occured,fix the errors and try again", + innerException: alreadyExistsVideoMetadataException); - this.storageBrokerMock.Setup(broker => - broker.InsertVideoMetadataAsync(someVideoMetadata)) - .ThrowsAsync(duplicateKeyException); + this.dateTimeBrokerMock.Setup(broker => broker.GetCurrentDateTimeOffset()) + .Throws(duplicateKeyException); //when - ValueTask addVideoMetadata = - this.videoMetadataService.AddVideoMetadataAsync(someVideoMetadata); + ValueTask addVideoMetadataTask = this.videoMetadataService + .AddVideoMetadataAsync(randomVideoMetadata); - var actualVideoMetadataDependencyValidationException = - await Assert.ThrowsAsync(addVideoMetadata.AsTask); + VideoMetadataDependencyValidationException actualVideoMetadataDependencyValidationException = + await Assert.ThrowsAsync(addVideoMetadataTask.AsTask); //then - actualVideoMetadataDependencyValidationException.Should() + actualVideoMetadataDependencyValidationException.Should() .BeEquivalentTo(expectedVideoMetadataDependencyValidationException); - this.storageBrokerMock.Verify(broker => - broker.InsertVideoMetadataAsync(someVideoMetadata), - Times.Once); + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffset(), Times.Once); - this.loggingBrokerMock.Verify(broker => - broker.LogError(It.Is(SameExceptionAs( - expectedVideoMetadataDependencyValidationException))), - Times.Once); + this.loggingBrokerMock.Verify(broker => broker.LogError(It.Is( + SameExceptionAs(expectedVideoMetadataDependencyValidationException))), Times.Once); - this.storageBrokerMock.VerifyNoOtherCalls(); + this.dateTimeBrokerMock.VerifyNoOtherCalls(); this.loggingBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); } [Fact] - public async Task ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync() + public async Task ShouldThrowDependencyExceptionOnAddIfDbUpdateErrorOccursAndLogItAsync() { //given - VideoMetadata someVideoMetadata = CreateRandomVideoMetadata(); - var dbUpdateConcurrencyException = new DbUpdateConcurrencyException(); + VideoMetadata randomVideoMetadata = CreateRandomVideoMetadata(); + var dbUpdateException = new DbUpdateException(); - var lockedVideoMetadataException = - new LockedVideoMetadataException("Video Metadata is locked, please try again.", - dbUpdateConcurrencyException); + var failedVideoMetadataStorageException = new FailedVideoMetadataStorageException( + message: "Failed video metadata error occured, contact support", + innerException: dbUpdateException); - VideoMetadataDependencyValidationException expectedVideoMetadataDependencyValidationException = - new VideoMetadataDependencyValidationException( - "Video metadata dependency error occurred,fix the errors try again", - lockedVideoMetadataException); + var expectedVideoMetadataDependencyException = + new VideoMetadataDependencyException( + message: "Video metadata dependency error occured, fix the errors and try again", + innerException: failedVideoMetadataStorageException); this.dateTimeBrokerMock.Setup(broker => broker.GetCurrentDateTimeOffset()) - .Throws(dbUpdateConcurrencyException); + .Throws(dbUpdateException); //when - ValueTask addVideoMetadataTask = - this.videoMetadataService.AddVideoMetadataAsync(someVideoMetadata); + ValueTask addVideoMetadataTask = this.videoMetadataService.AddVideoMetadataAsync( + videoMetadata: randomVideoMetadata); - var actualVideoMetadataDependencyValidationException = - await Assert.ThrowsAsync(addVideoMetadataTask.AsTask); + VideoMetadataDependencyException actualVideoMetadataDependencyException = + await Assert.ThrowsAsync(addVideoMetadataTask.AsTask); //then - actualVideoMetadataDependencyValidationException.Should() - .BeEquivalentTo(expectedVideoMetadataDependencyValidationException); + actualVideoMetadataDependencyException.Should() + .BeEquivalentTo(expectedVideoMetadataDependencyException); this.dateTimeBrokerMock.Verify(broker => broker.GetCurrentDateTimeOffset(), Times.Once); - this.loggingBrokerMock.Verify(broker => - broker.LogError(It.Is(SameExceptionAs(expectedVideoMetadataDependencyValidationException))), - Times.Once); + this.loggingBrokerMock.Verify(broker => broker.LogError(It.Is( + SameExceptionAs(expectedVideoMetadataDependencyException))), Times.Once); this.storageBrokerMock.Verify(broker => - broker.InsertVideoMetadataAsync(someVideoMetadata), Times.Never); + broker.UpdateVideoMetadataAsync(It.IsAny()), Times.Never); this.dateTimeBrokerMock.VerifyNoOtherCalls(); this.storageBrokerMock.VerifyNoOtherCalls(); diff --git a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Logic.Add.cs b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Logic.Add.cs index 5f140be..f817b94 100644 --- a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Logic.Add.cs +++ b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Logic.Add.cs @@ -15,11 +15,14 @@ public partial class VideoMetadataServiceTest public async Task ShouldAddVideoMetadataAsync() { //give - VideoMetadata randomVideoMetadata = CreateRandomVideoMetadata(); + DateTimeOffset randomDate = GetRandomDateTime(); + VideoMetadata randomVideoMetadata = CreateRandomVideoMetadata(randomDate); VideoMetadata inputVideoMetadata = randomVideoMetadata; VideoMetadata returningVideoMetadata = inputVideoMetadata; VideoMetadata expectedVideoMetadata = returningVideoMetadata.DeepClone(); + this.dateTimeBrokerMock.Setup(broker => + broker.GetCurrentDateTimeOffset()).Returns(randomDate); this.storageBrokerMock.Setup(broker => broker.InsertVideoMetadataAsync(inputVideoMetadata)).ReturnsAsync(expectedVideoMetadata); //when @@ -27,7 +30,8 @@ public async Task ShouldAddVideoMetadataAsync() await this.videoMetadataService.AddVideoMetadataAsync(inputVideoMetadata); //then actualVideoMetadata.Should().BeEquivalentTo(expectedVideoMetadata); - + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffset(), Times.Once); this.storageBrokerMock.Verify(broker => broker.InsertVideoMetadataAsync(inputVideoMetadata), Times.Once()); diff --git a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs index 0c1025c..5b4da54 100644 --- a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs +++ b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.cs @@ -4,7 +4,6 @@ //================================================= using Microsoft.Data.SqlClient; using Moq; -using System.Data.SqlTypes; using System.Linq.Expressions; using System.Runtime.Serialization; using Tynamix.ObjectFiller; @@ -28,31 +27,35 @@ public VideoMetadataServiceTest() { this.storageBrokerMock = new Mock(); this.loggingBrokerMock = new Mock(); - this.dateTimeBrokerMock= new Mock(); + this.dateTimeBrokerMock = new Mock(); this.videoMetadataService = new VideoMetadataService (storageBroker: this.storageBrokerMock.Object, - loggingBroker: loggingBrokerMock.Object, + loggingBroker: this.loggingBrokerMock.Object, dateTimeBroker:this.dateTimeBrokerMock.Object); } private Expression> SameExceptionAs(Xeption expectedException) => actualException => actualException.SameExceptionAs(expectedException); + private static DateTimeOffset GetRandomDateTime() => + new DateTimeRange(earliestDate: DateTime.UnixEpoch).GetValue(); + private static VideoMetadata CreateRandomVideoMetadata() => - CreateVideoMetadataFiller(date: GetRandomDateTimeOffset()).Create(); - public static DateTimeOffset GetRandomDateTimeOffset() => - new DateTimeRange(earliestDate: new DateTime()).GetValue(); + CreateVideoMetadataFiller(GetRandomDateTime()).Create(); - private static Filler CreateVideoMetadataFiller(DateTimeOffset date) + public static VideoMetadata CreateRandomVideoMetadata(DateTimeOffset date) => + CreateVideoMetadataFiller(date).Create(); + + private static Filler CreateVideoMetadataFiller(DateTimeOffset dates) { var filler = new Filler(); filler.Setup() - .OnType().Use(date); + .OnType().Use(dates); return filler; } - private static SqlException GetSqlException()=> + private static SqlException GetSqlException() => (SqlException)FormatterServices.GetUninitializedObject(typeof(SqlException)); private static string GetRandomString() { From 73dbdb9413e2cb621a8d588c04626efbea855f60 Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 16:49:09 +0500 Subject: [PATCH 6/8] ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync->FAIL --- ...VideoMetadataServiceTest.Exceptions.Add.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs index dfa73de..b1a9bba 100644 --- a/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs +++ b/UsefulTime.Unit.Tests/Services/Foundations/VideoMetadatas/VideoMetadataServiceTest.Exceptions.Add.cs @@ -98,6 +98,51 @@ public async Task ShouldThrowDependencyValidationExceptionOnAddIfDublicateKeyErr this.storageBrokerMock.VerifyNoOtherCalls(); } [Fact] + public async Task ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync() + { + //given + VideoMetadata someVideoMetadata = CreateRandomVideoMetadata(); + var dbUpdateConcurrencyException = new DbUpdateConcurrencyException(); + + var lockedVideoMetadataException = + new LockedVideoMetadataException("Video Metadata is locked, please try again", + dbUpdateConcurrencyException); + + VideoMetadataDependencyValidationException expectedVideoMetadataDependencyValidationException = + new VideoMetadataDependencyValidationException( + "Video metadata Dependency validation error occured,fix the errors and try again", + lockedVideoMetadataException); + + this.dateTimeBrokerMock.Setup(broker => + broker.GetCurrentDateTimeOffset()) + .Throws(dbUpdateConcurrencyException); + + //when + ValueTask addVideoMetadataTask = + this.videoMetadataService.AddVideoMetadataAsync(someVideoMetadata); + + var actualVideoMetadataDependencyValidationException = + await Assert.ThrowsAsync(addVideoMetadataTask.AsTask); + + //then + actualVideoMetadataDependencyValidationException.Should() + .BeEquivalentTo(expectedVideoMetadataDependencyValidationException); + + this.dateTimeBrokerMock.Verify(broker => + broker.GetCurrentDateTimeOffset(), Times.Once); + + this.loggingBrokerMock.Verify(broker => + broker.LogError(It.Is(SameExceptionAs(expectedVideoMetadataDependencyValidationException))), + Times.Once); + + this.storageBrokerMock.Verify(broker => + broker.InsertVideoMetadataAsync(someVideoMetadata), Times.Never); + + this.dateTimeBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } + [Fact] public async Task ShouldThrowDependencyExceptionOnAddIfDbUpdateErrorOccursAndLogItAsync() { //given From 806c9221fb4c500e3955ed8c0c7fd8108db9c259 Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 16:52:35 +0500 Subject: [PATCH 7/8] ShouldThrowDependencyValidationExceptionOnAddIfDbCurrencyErrorOccursAndLogItAsync-PASS --- .../VideoMetadataService.Exceptions.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs index f7c364b..acbb827 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs @@ -44,6 +44,14 @@ private async ValueTask TryCatch(ReturningVideoMetadataFunction r innerException: duplicateKeyException); throw CreateAndDependencyValidationException(alreadyExistVideoMetadataException); } + catch (DbUpdateConcurrencyException dbUpdateConcurrencyException) + { + LockedVideoMetadataException lockedVideoMetadataException = new LockedVideoMetadataException( + "Video Metadata is locked, please try again", + dbUpdateConcurrencyException); + + throw CreateAndLogDependencyValidationException(lockedVideoMetadataException); + } catch (DbUpdateException databaseUpdateException) { var failedVideoMetadataStorageException = new FailedVideoMetadataStorageException( @@ -105,5 +113,15 @@ private Exception CreateAndLogDependencyException(Xeption exception) return videoMetadataDependencyException; } + private VideoMetadataDependencyValidationException CreateAndLogDependencyValidationException(Xeption exception) + { + var videoMetadataDependencyValidationException = new VideoMetadataDependencyValidationException( + "Video metadata Dependency validation error occured,fix the errors and try again", + exception); + + this.loggingBroker.LogError(videoMetadataDependencyValidationException); + + return videoMetadataDependencyValidationException; + } } } From efa2c6c1e08ef1f922d16acf6709cf05cc34a3c6 Mon Sep 17 00:00:00 2001 From: "jaloliddin.mahkamov@mail.ru" Date: Wed, 29 May 2024 16:55:42 +0500 Subject: [PATCH 8/8] FOUNDATIONS:Tests --- .../VedioMetadatas/VideoMetadataService.Exceptions.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs index acbb827..b44781a 100644 --- a/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs +++ b/UsefulTime.Api/Services/Foundations/VedioMetadatas/VideoMetadataService.Exceptions.cs @@ -63,7 +63,9 @@ private async ValueTask TryCatch(ReturningVideoMetadataFunction r catch (Exception exception) { var failedVideoMetadataServiceException = - new FailedVideoMetadataServiceException(message: "Failed guest service error occurred,contact support",innerException:exception); + new FailedVideoMetadataServiceException( + message: "Failed guest service error occurred,contact support", + innerException:exception); throw CreateAndLogServiseException(failedVideoMetadataServiceException); }