Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//-----------------------------------------------------------
// 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 Microsoft.EntityFrameworkCore;
using Moq;

namespace LibraryManagement.Api.Tests.Unit.Services.Foundations.Readers
{
public partial class ReaderServiceTests
{
[Fact]
public async Task ShouldThrowDependencyValidationOnRemoveIfDatabaseUpdateConcurrencyErrorOccursAndLogItAsync()
{
// given
Guid someReaderId = Guid.NewGuid();
var dbUpdateConcurrencyException = new DbUpdateConcurrencyException();

var lockedReaderException =
new LockedReaderException(dbUpdateConcurrencyException);

var expectedReaderDependencyValidationException =
new ReaderDependencyValidationException(lockedReaderException);

this.storageBrokerMock.Setup(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()))
.ThrowsAsync(dbUpdateConcurrencyException);

// when
ValueTask<Reader> removeReaderById =
this.readerService.RemoveReaderByIdAsync(someReaderId);

ReaderDependencyValidationException actualReaderDependencyValidationException =
await Assert.ThrowsAsync<ReaderDependencyValidationException>(() =>
removeReaderById.AsTask());

// then
actualReaderDependencyValidationException.Should()
.BeEquivalentTo(expectedReaderDependencyValidationException);

this.storageBrokerMock.Verify(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()),
Times.Once);

this.loggingBrokerMock.Verify(broker =>
broker.LogError(It.Is(SameExceptionAs(
expectedReaderDependencyValidationException))),
Times.Once);

this.storageBrokerMock.Verify(broker =>
broker.DeleteReaderAsync(It.IsAny<Reader>()),
Times.Never);

this.storageBrokerMock.VerifyNoOtherCalls();
this.loggingBrokerMock.VerifyNoOtherCalls();
}

[Fact]
public async Task ShouldThrowDependencyExceptionOnRemoveWhenSqlExceptionOccursAndLogItAsync()
{
// given
Guid someLocationId = Guid.NewGuid();
SqlException sqlException = GetSqlError();

var failedReaderStorageException =
new FailedReaderStorageException(sqlException);

var expectedReaderDependencyException =
new ReaderDependencyException(failedReaderStorageException);

this.storageBrokerMock.Setup(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()))
.ThrowsAsync(sqlException);

// when
ValueTask<Reader> deleteReaderTask =
this.readerService.RemoveReaderByIdAsync(someLocationId);

ReaderDependencyException actualReaderDependencyException =
await Assert.ThrowsAsync<ReaderDependencyException>(() =>
deleteReaderTask.AsTask());

// then
actualReaderDependencyException.Should()
.BeEquivalentTo(expectedReaderDependencyException);

this.storageBrokerMock.Verify(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()),
Times.Once);

this.loggingBrokerMock.Verify(broker =>
broker.LogCritical(It.Is(SameExceptionAs(
expectedReaderDependencyException))),
Times.Once);

this.storageBrokerMock.VerifyNoOtherCalls();
this.loggingBrokerMock.VerifyNoOtherCalls();
}

[Fact]
public async Task ShouldThrowServiceExceptionOnRemoveIfExceptionOccursAndLogItAsync()
{
// given
Guid someReaderId = Guid.NewGuid();
var serviceException = new Exception();

var failedReaderServiceException =
new FailedReaderServiceException(serviceException);

var expectedReaderServiceException =
new ReaderServiceException(failedReaderServiceException);

this.storageBrokerMock.Setup(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()))
.ThrowsAsync(serviceException);

// when
ValueTask<Reader> removeReaderByIdTask =
this.readerService.RemoveReaderByIdAsync(someReaderId);

ReaderServiceException actualReaderServiceException =
await Assert.ThrowsAsync<ReaderServiceException>(() =>
removeReaderByIdTask.AsTask());

// then
actualReaderServiceException.Should()
.BeEquivalentTo(expectedReaderServiceException);

this.storageBrokerMock.Verify(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()),
Times.Once);

this.loggingBrokerMock.Verify(broker =>
broker.LogError(It.Is(SameExceptionAs(
expectedReaderServiceException))),
Times.Once);

this.storageBrokerMock.VerifyNoOtherCalls();
this.loggingBrokerMock.VerifyNoOtherCalls();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//-----------------------------------------------------------
// 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 async Task ShouldRemoveReaderByIdAsync()
{
// given
Guid randomId = Guid.NewGuid();
Guid inputReaderId = randomId;
Reader randomReader = CreateRandomReader();
Reader storageReader = randomReader;
Reader expectedInputReader = storageReader;
Reader deletedReader = expectedInputReader;
Reader expectedReader = deletedReader.DeepClone();

this.storageBrokerMock.Setup(broker =>
broker.SelectReaderByIdAsync(inputReaderId))
.ReturnsAsync(storageReader);

this.storageBrokerMock.Setup(broker =>
broker.DeleteReaderAsync(expectedInputReader))
.ReturnsAsync(deletedReader);

// when
Reader actualReader =
await this.readerService.RemoveReaderByIdAsync(randomId);

// then
actualReader.Should().BeEquivalentTo(expectedReader);

this.storageBrokerMock.Verify(broker =>
broker.SelectReaderByIdAsync(inputReaderId),
Times.Once);

this.storageBrokerMock.Verify(broker =>
broker.DeleteReaderAsync(expectedInputReader),
Times.Once);

this.storageBrokerMock.VerifyNoOtherCalls();
this.loggingBrokerMock.VerifyNoOtherCalls();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//-----------------------------------------------------------
// 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 ShouldThrowValidationExceptionOnRemoveIfIdIsInvalidAndLogItAsync()
{
// 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<Reader> removeReaderById =
this.readerService.RemoveReaderByIdAsync(invalidReaderId);

ReaderValidationException actualReaderValidationException =
await Assert.ThrowsAsync<ReaderValidationException>(() =>
removeReaderById.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<Guid>()),
Times.Never);

this.storageBrokerMock.Verify(broker =>
broker.DeleteReaderAsync(It.IsAny<Reader>()),
Times.Never);

this.loggingBrokerMock.VerifyNoOtherCalls();
this.storageBrokerMock.VerifyNoOtherCalls();
}

[Fact]
public async Task ShouldThrowNotFoundExceptionOnRemoveReaderByIdIsNotFoundAndLogItAsync()
{
// given
Guid inputReaderId = Guid.NewGuid();
Reader noReader = null;

var notFoundReaderException =
new NotFoundReaderException(inputReaderId);

var expectedReaderValidationException =
new ReaderValidationException(notFoundReaderException);

this.storageBrokerMock.Setup(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()))
.ReturnsAsync(noReader);

// when
ValueTask<Reader> removeReaderById =
this.readerService.RemoveReaderByIdAsync(inputReaderId);

var actualReaderValidationException =
await Assert.ThrowsAsync<ReaderValidationException>(() =>
removeReaderById.AsTask());

// then
actualReaderValidationException.Should()
.BeEquivalentTo(expectedReaderValidationException);

this.storageBrokerMock.Verify(broker =>
broker.SelectReaderByIdAsync(It.IsAny<Guid>()),
Times.Once);

this.loggingBrokerMock.Verify(broker =>
broker.LogError(It.Is(SameExceptionAs(
expectedReaderValidationException))),
Times.Once);

this.storageBrokerMock.Verify(broker =>
broker.DeleteReaderAsync(It.IsAny<Reader>()),
Times.Never);

this.storageBrokerMock.VerifyNoOtherCalls();
this.loggingBrokerMock.VerifyNoOtherCalls();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ public interface IReaderService
IQueryable<Reader> RetrieveAllReaders();
ValueTask<Reader> RetrieveReaderByIdAsync(Guid readerId);
ValueTask<Reader> ModifyReaderAsync(Reader reader);
ValueTask<Reader> RemoveReaderByIdAsync(Guid readerId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,18 @@ public ValueTask<Reader> ModifyReaderAsync(Reader reader) =>

return await this.storageBroker.UpdateReaderAsync(reader);
});

public ValueTask<Reader> RemoveReaderByIdAsync(Guid readerId) =>
TryCatch(async () =>
{
ValidateReaderId(readerId);

Reader maybeReader =
await this.storageBroker.SelectReaderByIdAsync(readerId);

ValidateStorageReader(maybeReader, readerId);

return await this.storageBroker.DeleteReaderAsync(maybeReader);
});
}
}
Loading