From e3f896d4f4f1d9fc15d1633e2fa006e99120b672 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:08:23 +0500 Subject: [PATCH 01/18] ShouldRetrieveAllReaders -> FAIL --- .../ReaderServiceTests.Logic.RetrieveAll.cs | 42 +++++++++++++++++++ .../Foundations/Readers/ReaderServiceTests.cs | 9 ++++ .../Foundations/Readers/IReaderService.cs | 1 + .../Foundations/Readers/ReaderService.cs | 3 ++ 4 files changed, 55 insertions(+) create mode 100644 LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs new file mode 100644 index 0000000..c0ceeb9 --- /dev/null +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs @@ -0,0 +1,42 @@ +//----------------------------------------------------------- +// Copyright (c) Coalition of Good-Hearted Engineers +// Free To Use To Build Reliable Library Management Solutions +//----------------------------------------------------------- + +using FluentAssertions; +using Force.DeepCloner; +using LibraryManagement.Api.Models.Foundations.Readers; +using Moq; + +namespace LibraryManagement.Api.Tests.Unit.Services.Foundations.Readers +{ + public partial class ReaderServiceTests + { + [Fact] + public void ShouldRetrieveAllReaders() + { + // given + IQueryable randomReader = CreateRandomReaders(); + IQueryable storageReader = randomReader; + IQueryable expectedReader = storageReader; + + this.storageBrokerMock.Setup(broker => + broker.SelectAllReaders()) + .Returns(storageReader); + + // when + IQueryable actualReader = + this.readerService.RetrieveAllReaders(); + + // then + actualReader.Should().BeEquivalentTo(expectedReader); + + this.storageBrokerMock.Verify(broker => + broker.SelectAllReaders(), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } + } +} diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.cs index 184c932..344bb53 100644 --- a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.cs +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.cs @@ -37,6 +37,15 @@ private static Reader CreateRandomReader() => private static DateTimeOffset GetRandomDateTimeOffset() => new DateTimeRange(earliestDate: new DateTime()).GetValue(); + private IQueryable CreateRandomReaders() + { + return CreateReaderFiller(GetRandomDateTimeOffset()) + .Create(count: GetRandomNumber()).AsQueryable(); + } + + private static int GetRandomNumber() => + new IntRange(2, 9).GetValue(); + private static SqlException GetSqlError() => (SqlException)RuntimeHelpers.GetUninitializedObject(typeof(SqlException)); diff --git a/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs index 35410d3..b427b86 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs @@ -10,5 +10,6 @@ namespace LibraryManagement.Api.Services.Foundations.Readers public interface IReaderService { ValueTask AddReaderAsync(Reader reader); + IQueryable RetrieveAllReaders(); } } diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index 5c99c30..ce5e4bd 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -29,5 +29,8 @@ public ValueTask AddReaderAsync(Reader reader) => return await this.storageBroker.InsertReaderAsync(reader); }); + + public IQueryable RetrieveAllReaders() => + throw new NotImplementedException(); } } From 6a4e41fe24851d31870d4bfd2f5aac774a263f85 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:09:11 +0500 Subject: [PATCH 02/18] ShouldRetrieveAllReaders -> PASS --- .../Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs | 2 +- .../Services/Foundations/Readers/ReaderService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs index c0ceeb9..49a4868 100644 --- a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveAll.cs @@ -18,7 +18,7 @@ public void ShouldRetrieveAllReaders() // given IQueryable randomReader = CreateRandomReaders(); IQueryable storageReader = randomReader; - IQueryable expectedReader = storageReader; + IQueryable expectedReader = storageReader.DeepClone(); this.storageBrokerMock.Setup(broker => broker.SelectAllReaders()) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index ce5e4bd..c20b1f9 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -31,6 +31,6 @@ public ValueTask AddReaderAsync(Reader reader) => }); public IQueryable RetrieveAllReaders() => - throw new NotImplementedException(); + this.storageBroker.SelectAllReaders(); } } From f7812986e6d36fcfce97441a41f2ad3bfeff5307 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:11:04 +0500 Subject: [PATCH 03/18] ShouldThrowCriticalDependencyExceptionOnRetrieveAllWhenSqlExceptionOccursAndLogIt -> FAIL --- ...aderServiceTests.Exceptions.RetrieveAll.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs new file mode 100644 index 0000000..ce33b21 --- /dev/null +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs @@ -0,0 +1,54 @@ +//----------------------------------------------------------- +// Copyright (c) Coalition of Good-Hearted Engineers +// Free To Use To Build Reliable Library Management Solutions +//----------------------------------------------------------- + +using FluentAssertions; +using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; +using Microsoft.Data.SqlClient; +using Moq; + +namespace LibraryManagement.Api.Tests.Unit.Services.Foundations.Readers +{ + public partial class ReaderServiceTests + { + [Fact] + public void ShouldThrowCriticalDependencyExceptionOnRetrieveAllWhenSqlExceptionOccursAndLogIt() + { + // given + SqlException sqlException = GetSqlError(); + + var failedReaderStorageException = + new FailedReaderStorageException(sqlException); + + var expectedReaderDependencyException = + new ReaderDependencyException(failedReaderStorageException); + + this.storageBrokerMock.Setup(broker => + broker.SelectAllReaders()).Throws(sqlException); + + // when + Action retrieveAllReadersAction = () => + this.readerService.RetrieveAllReaders(); + + ReaderDependencyException actualReaderDependencyException = + Assert.Throws(retrieveAllReadersAction); + + // then + actualReaderDependencyException.Should() + .BeEquivalentTo(expectedReaderDependencyException); + + this.storageBrokerMock.Verify(broker => + broker.SelectAllReaders(), + Times.Once()); + + this.loggingBrokerMock.Verify(broker => + broker.LogCritical(It.Is(SameExceptionAs( + expectedReaderDependencyException))), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } + } +} From 5a5f132452bb9911a2c9bb5da99cc1d1dd75473a Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:12:36 +0500 Subject: [PATCH 04/18] ShouldThrowCriticalDependencyExceptionOnRetrieveAllWhenSqlExceptionOccursAndLogIt -> PASS --- .../Foundations/Readers/ReaderService.cs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index c20b1f9..f9ed322 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -6,6 +6,8 @@ using LibraryManagement.Api.Brokers.Loggings; using LibraryManagement.Api.Brokers.Storages; using LibraryManagement.Api.Models.Foundations.Readers; +using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; +using Microsoft.Data.SqlClient; namespace LibraryManagement.Api.Services.Foundations.Readers { @@ -30,7 +32,24 @@ public ValueTask AddReaderAsync(Reader reader) => return await this.storageBroker.InsertReaderAsync(reader); }); - public IQueryable RetrieveAllReaders() => - this.storageBroker.SelectAllReaders(); + public IQueryable RetrieveAllReaders() + { + try + { + return this.storageBroker.SelectAllReaders(); + } + catch (SqlException sqlException) + { + var failedReaderStorageException = + new FailedReaderStorageException(sqlException); + + var readerDependencyException = + new ReaderDependencyException(failedReaderStorageException); + + this.loggingBroker.LogCritical(readerDependencyException); + + throw readerDependencyException; + } + } } } From aa02edcc84a87d983bdb68029ae09c625b30710e Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:13:31 +0500 Subject: [PATCH 05/18] ShouldThrowServiceExceptionOnRetrieveAllIfServiceErrorOccursAndLogItAsync -> FAIL --- ...aderServiceTests.Exceptions.RetrieveAll.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs index ce33b21..dba93ee 100644 --- a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveAll.cs @@ -50,5 +50,45 @@ public void ShouldThrowCriticalDependencyExceptionOnRetrieveAllWhenSqlExceptionO this.storageBrokerMock.VerifyNoOtherCalls(); this.loggingBrokerMock.VerifyNoOtherCalls(); } + + [Fact] + public void ShouldThrowServiceExceptionOnRetrieveAllIfServiceErrorOccursAndLogItAsync() + { + // given + string exceptionMessage = GetRandomString(); + var serverException = new Exception(exceptionMessage); + + var failedReaderServiceException = + new FailedReaderServiceException(serverException); + + var expectedReaderServiceException = + new ReaderServiceException(failedReaderServiceException); + + this.storageBrokerMock.Setup(broker => + broker.SelectAllReaders()).Throws(serverException); + + // when + Action retrieveAllReaderActions = () => + this.readerService.RetrieveAllReaders(); + + ReaderServiceException actualReaderServiceException = + Assert.Throws(retrieveAllReaderActions); + + // then + actualReaderServiceException.Should() + .BeEquivalentTo(expectedReaderServiceException); + + this.storageBrokerMock.Verify(broker => + broker.SelectAllReaders(), + Times.Once()); + + this.loggingBrokerMock.Verify(broker => + broker.LogError(It.Is(SameExceptionAs( + expectedReaderServiceException))), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } } } From 2480599479d83812be92acbc2d6e5c5ed4ea0473 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:14:44 +0500 Subject: [PATCH 06/18] ShouldThrowServiceExceptionOnRetrieveAllIfServiceErrorOccursAndLogItAsync -> PASS --- .../Services/Foundations/Readers/ReaderService.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index f9ed322..64e9f62 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -50,6 +50,18 @@ public IQueryable RetrieveAllReaders() throw readerDependencyException; } + catch (Exception exception) + { + var failedReaderServiceException = + new FailedReaderServiceException(exception); + + var readerServiceException = + new ReaderServiceException(failedReaderServiceException); + + this.loggingBroker.LogError(readerServiceException); + + throw readerServiceException; + } } } } From 07bf37b8573a1d8480e91da2e55e7a1125705303 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:19:38 +0500 Subject: [PATCH 07/18] CODE RUB: Implement TryCatch for RetrieveAllReaders --- .../Readers/ReaderService.Exceptions.cs | 23 ++++++++++++ .../Foundations/Readers/ReaderService.cs | 35 ++----------------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs index d45a0e7..873c888 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs @@ -14,6 +14,7 @@ namespace LibraryManagement.Api.Services.Foundations.Readers public partial class ReaderService { private delegate ValueTask ReturningReaderFunction(); + private delegate IQueryable ReturningReadersFunction(); private async ValueTask TryCatch(ReturningReaderFunction returningReaderFunction) { @@ -52,6 +53,28 @@ private async ValueTask TryCatch(ReturningReaderFunction returningReader } } + private IQueryable TryCatch(ReturningReadersFunction returningReadersFunction) + { + try + { + return returningReadersFunction(); + } + catch (SqlException sqlException) + { + var failedReaderStorageException = + new FailedReaderStorageException(sqlException); + + throw CreateAndLogCriticalDependencyException(failedReaderStorageException); + } + catch (Exception exception) + { + var failedReaderServiceException = + new FailedReaderServiceException(exception); + + throw CreateAndLogServiceException(failedReaderServiceException); + } + } + private ReaderValidationException CreateAndLogValidationException(Xeption exception) { var readerValidationException = diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index 64e9f62..cc33fb9 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -6,8 +6,6 @@ using LibraryManagement.Api.Brokers.Loggings; using LibraryManagement.Api.Brokers.Storages; using LibraryManagement.Api.Models.Foundations.Readers; -using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; -using Microsoft.Data.SqlClient; namespace LibraryManagement.Api.Services.Foundations.Readers { @@ -32,36 +30,7 @@ public ValueTask AddReaderAsync(Reader reader) => return await this.storageBroker.InsertReaderAsync(reader); }); - public IQueryable RetrieveAllReaders() - { - try - { - return this.storageBroker.SelectAllReaders(); - } - catch (SqlException sqlException) - { - var failedReaderStorageException = - new FailedReaderStorageException(sqlException); - - var readerDependencyException = - new ReaderDependencyException(failedReaderStorageException); - - this.loggingBroker.LogCritical(readerDependencyException); - - throw readerDependencyException; - } - catch (Exception exception) - { - var failedReaderServiceException = - new FailedReaderServiceException(exception); - - var readerServiceException = - new ReaderServiceException(failedReaderServiceException); - - this.loggingBroker.LogError(readerServiceException); - - throw readerServiceException; - } - } + public IQueryable RetrieveAllReaders() => + TryCatch(() => this.storageBroker.SelectAllReaders()); } } From 29e8467c6c64cf91d9212d5163a95f1c392c8175 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:23:37 +0500 Subject: [PATCH 08/18] ShouldRetrieveReaderByIdAsync -> FAIL --- .../ReaderServiceTests.Logic.RetrieveById.cs | 43 +++++++++++++++++++ .../Foundations/Readers/IReaderService.cs | 1 + .../Foundations/Readers/ReaderService.cs | 3 ++ 3 files changed, 47 insertions(+) create mode 100644 LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs new file mode 100644 index 0000000..83f5967 --- /dev/null +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs @@ -0,0 +1,43 @@ +//----------------------------------------------------------- +// Copyright (c) Coalition of Good-Hearted Engineers +// Free To Use To Build Reliable Library Management Solutions +//----------------------------------------------------------- + +using FluentAssertions; +using LibraryManagement.Api.Models.Foundations.Readers; +using Moq; + +namespace LibraryManagement.Api.Tests.Unit.Services.Foundations.Readers +{ + public partial class ReaderServiceTests + { + [Fact] + public async Task ShouldRetrieveReaderByIdAsync() + { + // given + Guid randomReaderId = Guid.NewGuid(); + Guid inputReaderId = randomReaderId; + Reader randomReader = CreateRandomReader(); + Reader storageReader = randomReader; + Reader expectedReader = storageReader; + + this.storageBrokerMock.Setup(broker => + broker.SelectReaderByIdAsync(inputReaderId)) + .ReturnsAsync(storageReader); + + // when + Reader actualReader = await this + .readerService.RetrieveReaderByIdAsync(inputReaderId); + + // then + actualReader.Should().BeEquivalentTo(expectedReader); + + this.storageBrokerMock.Verify(broker => + broker.SelectReaderByIdAsync(inputReaderId), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } + } +} diff --git a/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs index b427b86..44822b2 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/IReaderService.cs @@ -11,5 +11,6 @@ public interface IReaderService { ValueTask AddReaderAsync(Reader reader); IQueryable RetrieveAllReaders(); + ValueTask RetrieveReaderByIdAsync(Guid readerId); } } diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index cc33fb9..c5595cd 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -32,5 +32,8 @@ public ValueTask AddReaderAsync(Reader reader) => public IQueryable RetrieveAllReaders() => TryCatch(() => this.storageBroker.SelectAllReaders()); + + public ValueTask RetrieveReaderByIdAsync(Guid readerId) => + throw new NotImplementedException(); } } From dbe98005a50274ceb0260ee2167c38085965c32b Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:25:04 +0500 Subject: [PATCH 09/18] ShouldRetrieveReaderByIdAsync -> PASS --- .../Readers/ReaderServiceTests.Logic.RetrieveById.cs | 3 ++- .../Services/Foundations/Readers/ReaderService.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs index 83f5967..1882fdc 100644 --- a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Logic.RetrieveById.cs @@ -4,6 +4,7 @@ //----------------------------------------------------------- using FluentAssertions; +using Force.DeepCloner; using LibraryManagement.Api.Models.Foundations.Readers; using Moq; @@ -19,7 +20,7 @@ public async Task ShouldRetrieveReaderByIdAsync() Guid inputReaderId = randomReaderId; Reader randomReader = CreateRandomReader(); Reader storageReader = randomReader; - Reader expectedReader = storageReader; + Reader expectedReader = storageReader.DeepClone(); this.storageBrokerMock.Setup(broker => broker.SelectReaderByIdAsync(inputReaderId)) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index c5595cd..41b71ae 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -33,7 +33,7 @@ public ValueTask AddReaderAsync(Reader reader) => public IQueryable RetrieveAllReaders() => TryCatch(() => this.storageBroker.SelectAllReaders()); - public ValueTask RetrieveReaderByIdAsync(Guid readerId) => - throw new NotImplementedException(); + public async ValueTask RetrieveReaderByIdAsync(Guid readerId) => + await this.storageBroker.SelectReaderByIdAsync(readerId); } } From 56280744fc636b43146c2704f6390babbf48279f Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:40:50 +0500 Subject: [PATCH 10/18] ShouldThrowValidationExceptionOnRetrieveByIdIfIdIsInvalidAndLogItAsync -> FAIL --- ...erServiceTests.Validations.RetrieveById.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs new file mode 100644 index 0000000..85c0955 --- /dev/null +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs @@ -0,0 +1,54 @@ +//----------------------------------------------------------- +// Copyright (c) Coalition of Good-Hearted Engineers +// Free To Use To Build Reliable Library Management Solutions +//----------------------------------------------------------- + +using FluentAssertions; +using LibraryManagement.Api.Models.Foundations.Readers; +using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; +using Moq; + +namespace LibraryManagement.Api.Tests.Unit.Services.Foundations.Readers +{ + public partial class ReaderServiceTests + { + [Fact] + public async Task ShouldThrowValidationExceptionOnRetrieveByIdIfIdIsInvalidAndLogItAsync() + { + // given + Guid invalidReaderId = Guid.Empty; + var invalidReaderException = new InvalidReaderException(); + + invalidReaderException.AddData( + key: nameof(Reader.ReaderId), + values: "Id is required"); + + var expectedReaderValidationException = + new ReaderValidationException(invalidReaderException); + + // when + ValueTask retrieveReaderById = + this.readerService.RetrieveReaderByIdAsync(invalidReaderId); + + ReaderValidationException actualReaderValidationException = + await Assert.ThrowsAsync(() => + retrieveReaderById.AsTask()); + + // then + actualReaderValidationException.Should() + .BeEquivalentTo(expectedReaderValidationException); + + this.loggingBrokerMock.Verify(broker => + broker.LogError(It.Is(SameExceptionAs( + expectedReaderValidationException))), + Times.Once); + + this.storageBrokerMock.Verify(broker => + broker.SelectReaderByIdAsync(It.IsAny()), + Times.Never); + + this.loggingBrokerMock.VerifyNoOtherCalls(); + this.storageBrokerMock.VerifyNoOtherCalls(); + } + } +} From 65d98b5255861181a7bf0a426c8d5f8b3439118a Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:49:18 +0500 Subject: [PATCH 11/18] ShouldThrowValidationExceptionOnRetrieveByIdIfIdIsInvalidAndLogItAsync -> PASS --- .../Readers/ReaderService.Validations.cs | 3 +++ .../Foundations/Readers/ReaderService.cs | 21 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs index d88a4d4..6333165 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs @@ -29,6 +29,9 @@ private void ValidateReaderNotNull(Reader reader) } } + private static void ValidateReaderId(Guid readerId) => + Validate((Rule: IsInvalid(readerId), Parameter: nameof(Reader.ReaderId))); + private static dynamic IsInvalid(Guid id) => new { Condition = id == Guid.Empty, diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index 41b71ae..c4da3ce 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -6,6 +6,7 @@ using LibraryManagement.Api.Brokers.Loggings; using LibraryManagement.Api.Brokers.Storages; using LibraryManagement.Api.Models.Foundations.Readers; +using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; namespace LibraryManagement.Api.Services.Foundations.Readers { @@ -33,7 +34,23 @@ public ValueTask AddReaderAsync(Reader reader) => public IQueryable RetrieveAllReaders() => TryCatch(() => this.storageBroker.SelectAllReaders()); - public async ValueTask RetrieveReaderByIdAsync(Guid readerId) => - await this.storageBroker.SelectReaderByIdAsync(readerId); + public async ValueTask RetrieveReaderByIdAsync(Guid readerId) + { + try + { + ValidateReaderId(readerId); + + return await this.storageBroker.SelectReaderByIdAsync(readerId); + } + catch (InvalidReaderException invalidReaderException) + { + var readerValidationException = + new ReaderValidationException(invalidReaderException); + + this.loggingBroker.LogError(readerValidationException); + + throw readerValidationException; + } + } } } From 38530eea6a5449b9e56a2e22561fa6903f6c33bb Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:53:07 +0500 Subject: [PATCH 12/18] ShouldThrowValidationExceptionOnRetrieveByIdIfReaderNotFoundAndLogItAsync -> FAIL --- ...erServiceTests.Validations.RetrieveById.cs | 42 +++++++++++++++++++ .../Exceptions/NotFoundReaderException.cs | 16 +++++++ 2 files changed, 58 insertions(+) create mode 100644 LibraryManagement.Api/Models/Foundations/Readers/Exceptions/NotFoundReaderException.cs diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs index 85c0955..fc77836 100644 --- a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Validations.RetrieveById.cs @@ -50,5 +50,47 @@ await Assert.ThrowsAsync(() => this.loggingBrokerMock.VerifyNoOtherCalls(); this.storageBrokerMock.VerifyNoOtherCalls(); } + + [Fact] + public async Task ShouldThrowValidationExceptionOnRetrieveByIdIfReaderNotFoundAndLogItAsync() + { + // given + Guid someReaderId = Guid.NewGuid(); + Reader noReader = null; + + var notFoundReaderException = + new NotFoundReaderException(someReaderId); + + var expectedReaderValidationException = + new ReaderValidationException(notFoundReaderException); + + this.storageBrokerMock.Setup(broker => + broker.SelectReaderByIdAsync(It.IsAny())) + .ReturnsAsync(noReader); + + // when + ValueTask retriveByIdReaderTask = + this.readerService.RetrieveReaderByIdAsync(someReaderId); + + var actualReaderValidationException = + await Assert.ThrowsAsync(() => + retriveByIdReaderTask.AsTask()); + + // then + actualReaderValidationException.Should() + .BeEquivalentTo(expectedReaderValidationException); + + this.storageBrokerMock.Verify(broker => + broker.SelectReaderByIdAsync(someReaderId), + Times.Once); + + this.loggingBrokerMock.Verify(broker => + broker.LogError(It.Is(SameExceptionAs( + expectedReaderValidationException))), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } } } diff --git a/LibraryManagement.Api/Models/Foundations/Readers/Exceptions/NotFoundReaderException.cs b/LibraryManagement.Api/Models/Foundations/Readers/Exceptions/NotFoundReaderException.cs new file mode 100644 index 0000000..6a59047 --- /dev/null +++ b/LibraryManagement.Api/Models/Foundations/Readers/Exceptions/NotFoundReaderException.cs @@ -0,0 +1,16 @@ +//----------------------------------------------------------- +// Copyright (c) Coalition of Good-Hearted Engineers +// Free To Use To Build Reliable Library Management Solutions +//----------------------------------------------------------- + +using Xeptions; + +namespace LibraryManagement.Api.Models.Foundations.Readers.Exceptions +{ + public class NotFoundReaderException : Xeption + { + public NotFoundReaderException(Guid readerId) + : base(message: $"Reader is not found with id: {readerId}") + { } + } +} From 58a660bb9c793fd01eef1058fbc170291215a85f Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 15:56:26 +0500 Subject: [PATCH 13/18] ShouldThrowValidationExceptionOnRetrieveByIdIfReaderNotFoundAndLogItAsync -> PASS --- .../Readers/ReaderService.Validations.cs | 8 ++++++++ .../Foundations/Readers/ReaderService.cs | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs index 6333165..613cb5e 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Validations.cs @@ -32,6 +32,14 @@ private void ValidateReaderNotNull(Reader reader) private static void ValidateReaderId(Guid readerId) => Validate((Rule: IsInvalid(readerId), Parameter: nameof(Reader.ReaderId))); + private static void ValidateStorageReader(Reader maybeReader, Guid readerId) + { + if (maybeReader is null) + { + throw new NotFoundReaderException(readerId); + } + } + private static dynamic IsInvalid(Guid id) => new { Condition = id == Guid.Empty, diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index c4da3ce..99c0292 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -40,7 +40,12 @@ public async ValueTask RetrieveReaderByIdAsync(Guid readerId) { ValidateReaderId(readerId); - return await this.storageBroker.SelectReaderByIdAsync(readerId); + Reader maybeReader = + await this.storageBroker.SelectReaderByIdAsync(readerId); + + ValidateStorageReader(maybeReader, readerId); + + return maybeReader; } catch (InvalidReaderException invalidReaderException) { @@ -49,6 +54,15 @@ public async ValueTask RetrieveReaderByIdAsync(Guid readerId) this.loggingBroker.LogError(readerValidationException); + throw readerValidationException; + } + catch (NotFoundReaderException notFoundReaderException) + { + var readerValidationException = + new ReaderValidationException(notFoundReaderException); + + this.loggingBroker.LogError(readerValidationException); + throw readerValidationException; } } From daa7cc0c55edd125d5ded50c52ee4ba72770fe92 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 16:15:29 +0500 Subject: [PATCH 14/18] ShouldThrowCriticalDependencyExceptionOnRetrieveByIdIfSqlErrorOccursAndLogItAsync -> FAIL --- ...derServiceTests.Exceptions.RetrieveById.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs new file mode 100644 index 0000000..a3017e5 --- /dev/null +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------- +// Copyright (c) Coalition of Good-Hearted Engineers +// Free To Use To Build Reliable Library Management Solutions +//----------------------------------------------------------- + +using FluentAssertions; +using LibraryManagement.Api.Models.Foundations.Readers; +using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; +using Microsoft.Data.SqlClient; +using Moq; + +namespace LibraryManagement.Api.Tests.Unit.Services.Foundations.Readers +{ + public partial class ReaderServiceTests + { + [Fact] + public async Task ShouldThrowCriticalDependencyExceptionOnRetrieveByIdIfSqlErrorOccursAndLogItAsync() + { + // given + Guid someId = Guid.NewGuid(); + SqlException sqlException = GetSqlError(); + + var failedReaderStorageException = + new FailedReaderStorageException(sqlException); + + var expectedReaderDependencyException = + new ReaderDependencyException(failedReaderStorageException); + + this.storageBrokerMock.Setup(broker => + broker.SelectReaderByIdAsync(It.IsAny())) + .ThrowsAsync(sqlException); + + // when + ValueTask retrieveReaderById = + this.readerService.RetrieveReaderByIdAsync(someId); + + ReaderDependencyException actualReaderDependencyException = + await Assert.ThrowsAsync(() => + retrieveReaderById.AsTask()); + + // then + actualReaderDependencyException.Should() + .BeEquivalentTo(expectedReaderDependencyException); + + this.storageBrokerMock.Verify(broker => + broker.SelectReaderByIdAsync(someId), + Times.Once()); + + this.loggingBrokerMock.Verify(broker => + broker.LogCritical(It.Is(SameExceptionAs( + expectedReaderDependencyException))), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } + } +} From 823e9d1d63ad3df6ae51b8dc8a4dedf9dd69e206 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 16:16:35 +0500 Subject: [PATCH 15/18] ShouldThrowCriticalDependencyExceptionOnRetrieveByIdIfSqlErrorOccursAndLogItAsync -> PASS --- .../Services/Foundations/Readers/ReaderService.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index 99c0292..1fd09ff 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -7,6 +7,7 @@ using LibraryManagement.Api.Brokers.Storages; using LibraryManagement.Api.Models.Foundations.Readers; using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; +using Microsoft.Data.SqlClient; namespace LibraryManagement.Api.Services.Foundations.Readers { @@ -65,6 +66,18 @@ public async ValueTask RetrieveReaderByIdAsync(Guid readerId) throw readerValidationException; } + catch (SqlException sqlException) + { + var failedReaderStorageException = + new FailedReaderStorageException(sqlException); + + var readerDependencyException = + new ReaderDependencyException(failedReaderStorageException); + + this.loggingBroker.LogCritical(readerDependencyException); + + throw readerDependencyException; + } } } } From 122dd10d2d0f1ac37e3ecba431eeef0829b936c1 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 16:18:12 +0500 Subject: [PATCH 16/18] ShouldThrowServiceExceptionOnRetrieveByIdAsyncIfServiceErrorOccursAndLogItAsync -> FAIL --- ...derServiceTests.Exceptions.RetrieveById.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs index a3017e5..3ba27b6 100644 --- a/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs +++ b/LibraryManagement.Api.Tests.Unit/Services/Foundations/Readers/ReaderServiceTests.Exceptions.RetrieveById.cs @@ -54,5 +54,47 @@ await Assert.ThrowsAsync(() => this.storageBrokerMock.VerifyNoOtherCalls(); this.loggingBrokerMock.VerifyNoOtherCalls(); } + + [Fact] + public async Task ShouldThrowServiceExceptionOnRetrieveByIdAsyncIfServiceErrorOccursAndLogItAsync() + { + // given + Guid someId = Guid.NewGuid(); + var serverException = new Exception(); + + var failedReaderServiceException = + new FailedReaderServiceException(serverException); + + var expectedReaderServiceException = + new ReaderServiceException(failedReaderServiceException); + + this.storageBrokerMock.Setup(broker => + broker.SelectReaderByIdAsync(It.IsAny())) + .ThrowsAsync(serverException); + + // when + ValueTask retrieveReaderById = + this.readerService.RetrieveReaderByIdAsync(someId); + + ReaderServiceException actualReaderServiceException = + await Assert.ThrowsAsync(() => + retrieveReaderById.AsTask()); + + // then + actualReaderServiceException.Should() + .BeEquivalentTo(expectedReaderServiceException); + + this.storageBrokerMock.Verify(broker => + broker.SelectReaderByIdAsync(someId), + Times.Once); + + this.loggingBrokerMock.Verify(broker => + broker.LogError(It.Is(SameExceptionAs( + expectedReaderServiceException))), + Times.Once); + + this.storageBrokerMock.VerifyNoOtherCalls(); + this.loggingBrokerMock.VerifyNoOtherCalls(); + } } } From 9c7ea26d6182b9005fc7a8813a343cc6f7b9fc0f Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 16:19:27 +0500 Subject: [PATCH 17/18] ShouldThrowServiceExceptionOnRetrieveByIdAsyncIfServiceErrorOccursAndLogItAsync -> PASS --- .../Services/Foundations/Readers/ReaderService.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index 1fd09ff..2717740 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -78,6 +78,18 @@ public async ValueTask RetrieveReaderByIdAsync(Guid readerId) throw readerDependencyException; } + catch (Exception exception) + { + var failedReaderServiceException = + new FailedReaderServiceException(exception); + + var readerServiceException = + new ReaderServiceException(failedReaderServiceException); + + this.loggingBroker.LogError(readerServiceException); + + throw readerServiceException; + } } } } From 63645f79e9192d973cb1215eebd7c47ca013eb18 Mon Sep 17 00:00:00 2001 From: DilmurodDeveloper Date: Mon, 21 Jul 2025 16:22:47 +0500 Subject: [PATCH 18/18] CODE RUB: Implement TryCatch for RetrieveReaderByIdAsync --- .../Readers/ReaderService.Exceptions.cs | 4 ++ .../Foundations/Readers/ReaderService.cs | 62 +++---------------- 2 files changed, 12 insertions(+), 54 deletions(-) diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs index 873c888..c046ebc 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.Exceptions.cs @@ -30,6 +30,10 @@ private async ValueTask TryCatch(ReturningReaderFunction returningReader { throw CreateAndLogValidationException(invalidReaderException); } + catch (NotFoundReaderException notFoundReaderException) + { + throw CreateAndLogValidationException(notFoundReaderException); + } catch (SqlException sqlException) { var failedReaderStorageException = diff --git a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs index 2717740..a6a7753 100644 --- a/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs +++ b/LibraryManagement.Api/Services/Foundations/Readers/ReaderService.cs @@ -6,8 +6,6 @@ using LibraryManagement.Api.Brokers.Loggings; using LibraryManagement.Api.Brokers.Storages; using LibraryManagement.Api.Models.Foundations.Readers; -using LibraryManagement.Api.Models.Foundations.Readers.Exceptions; -using Microsoft.Data.SqlClient; namespace LibraryManagement.Api.Services.Foundations.Readers { @@ -35,61 +33,17 @@ public ValueTask AddReaderAsync(Reader reader) => public IQueryable RetrieveAllReaders() => TryCatch(() => this.storageBroker.SelectAllReaders()); - public async ValueTask RetrieveReaderByIdAsync(Guid readerId) + public ValueTask RetrieveReaderByIdAsync(Guid readerId) => + TryCatch(async () => { - try - { - ValidateReaderId(readerId); - - Reader maybeReader = - await this.storageBroker.SelectReaderByIdAsync(readerId); - - ValidateStorageReader(maybeReader, readerId); - - return maybeReader; - } - catch (InvalidReaderException invalidReaderException) - { - var readerValidationException = - new ReaderValidationException(invalidReaderException); - - this.loggingBroker.LogError(readerValidationException); - - throw readerValidationException; - } - catch (NotFoundReaderException notFoundReaderException) - { - var readerValidationException = - new ReaderValidationException(notFoundReaderException); - - this.loggingBroker.LogError(readerValidationException); + ValidateReaderId(readerId); - throw readerValidationException; - } - catch (SqlException sqlException) - { - var failedReaderStorageException = - new FailedReaderStorageException(sqlException); + Reader maybeReader = + await this.storageBroker.SelectReaderByIdAsync(readerId); - var readerDependencyException = - new ReaderDependencyException(failedReaderStorageException); + ValidateStorageReader(maybeReader, readerId); - this.loggingBroker.LogCritical(readerDependencyException); - - throw readerDependencyException; - } - catch (Exception exception) - { - var failedReaderServiceException = - new FailedReaderServiceException(exception); - - var readerServiceException = - new ReaderServiceException(failedReaderServiceException); - - this.loggingBroker.LogError(readerServiceException); - - throw readerServiceException; - } - } + return maybeReader; + }); } }