From be1202d242cae4781c09c66a076500463b65f8d4 Mon Sep 17 00:00:00 2001 From: Simon Geering <25039878+SimonGeering@users.noreply.github.com> Date: Wed, 7 Apr 2021 11:44:31 +0100 Subject: [PATCH] #167 Added CurrencyCreateCommand --- ...encyController.CurrencyCreateRequestDto.cs | 19 +++++ .../CQRS/CurrencyCreateCommand_UnitTest.cs | 72 +++++++++++++++++++ .../CoreModule/CQRS/CurrencyCreateCommand.cs | 47 ++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 src/AdminAssistant.Blazor/Server/WebAPI/v1/CoreModule/CurrencyController.CurrencyCreateRequestDto.cs create mode 100644 src/AdminAssistant.Test/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand_UnitTest.cs create mode 100644 src/AdminAssistant/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand.cs diff --git a/src/AdminAssistant.Blazor/Server/WebAPI/v1/CoreModule/CurrencyController.CurrencyCreateRequestDto.cs b/src/AdminAssistant.Blazor/Server/WebAPI/v1/CoreModule/CurrencyController.CurrencyCreateRequestDto.cs new file mode 100644 index 00000000..b8c63b0c --- /dev/null +++ b/src/AdminAssistant.Blazor/Server/WebAPI/v1/CoreModule/CurrencyController.CurrencyCreateRequestDto.cs @@ -0,0 +1,19 @@ +using AdminAssistant.DomainModel.Modules.CoreModule; +using AdminAssistant.Framework.TypeMapping; +using Swashbuckle.AspNetCore.Annotations; + +namespace AdminAssistant.WebAPI.v1.CoreModule +{ + [SwaggerSchema(Required = new[] { "Symbol", "DecimalFormat" })] + public class CurrencyCreateRequestDto : IMapTo + { + [SwaggerSchema("The Currency identifier.", ReadOnly = true)] + public int CurrencyID { get; set; } + public string Symbol { get; set; } = string.Empty; + public string DecimalFormat { get; set; } = string.Empty; + + public void MapTo(AutoMapper.Profile profile) + => profile.CreateMap() + .ForMember(x => x.CurrencyID, opt => opt.Ignore()); + } +} diff --git a/src/AdminAssistant.Test/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand_UnitTest.cs b/src/AdminAssistant.Test/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand_UnitTest.cs new file mode 100644 index 00000000..c072c8cf --- /dev/null +++ b/src/AdminAssistant.Test/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand_UnitTest.cs @@ -0,0 +1,72 @@ +#pragma warning disable CA1707 // Identifiers should not contain underscores +using System.Threading.Tasks; +using AdminAssistant.Infra.DAL.Modules.CoreModule; +using Ardalis.Result; +using FluentAssertions; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; +using ObjectCloner.Extensions; // https://github.com/marcelltoth/ObjectCloner + +namespace AdminAssistant.DomainModel.Modules.CoreModule.CQRS +{ + public class CurrencyCreateCommand_Should + { + [Fact] + [Trait("Category", "Unit")] + public async Task Return_APersistedCurrency_GivenAValidCurrency() + { + // Arrange + var currency = Factory.Currency.WithTestData().Build(); + + var services = new ServiceCollection(); + services.AddMockServerSideLogging(); + services.AddAdminAssistantServerSideDomainModel(); + + var mockCurrencyRepository = new Mock(); + mockCurrencyRepository.Setup(x => x.SaveAsync(currency)) + .Returns(() => + { + var result = currency.DeepClone(); + result = result with { CurrencyID = 30 }; + return Task.FromResult(result); + }); + + services.AddTransient((sp) => mockCurrencyRepository.Object); + + // Act + var result = await services.BuildServiceProvider().GetRequiredService().Send(new CurrencyCreateCommand(currency)).ConfigureAwait(false); + + // Assert + result.Should().NotBeNull(); + result.Status.Should().Be(ResultStatus.Ok); + result.ValidationErrors.Should().BeEmpty(); + result.Value.Should().NotBeNull(); + result.Value.CurrencyID.Should().BeGreaterThan(Constants.NewRecordID); + } + + [Fact] + [Trait("Category", "Unit")] + public async Task Return_ValidationError_GivenAnInvalidBank() + { + // Arrange + var services = new ServiceCollection(); + services.AddMockServerSideLogging(); + services.AddAdminAssistantServerSideDomainModel(); + services.AddTransient((sp) => new Mock().Object); + + var bank = Factory.Currency.WithTestData() + .WithoutASymbol() + .Build(); + // Act + var result = await services.BuildServiceProvider().GetRequiredService().Send(new CurrencyCreateCommand(bank)).ConfigureAwait(false); + + // Assert + result.Should().NotBeNull(); + result.Status.Should().Be(ResultStatus.Invalid); + result.ValidationErrors.Should().NotBeEmpty(); + } + } +} +#pragma warning restore CA1707 // Identifiers should not contain underscores diff --git a/src/AdminAssistant/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand.cs b/src/AdminAssistant/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand.cs new file mode 100644 index 00000000..5c8491a6 --- /dev/null +++ b/src/AdminAssistant/DomainModel/Modules/CoreModule/CQRS/CurrencyCreateCommand.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AdminAssistant.Infra.DAL.Modules.CoreModule; +using AdminAssistant.DomainModel.Modules.CoreModule.Validation; +using AdminAssistant.Infra.Providers; +using Ardalis.Result; +using MediatR; +using Ardalis.Result.FluentValidation; + +namespace AdminAssistant.DomainModel.Modules.CoreModule.CQRS +{ + public class CurrencyCreateCommand : IRequest> + { + public CurrencyCreateCommand(Currency currency) => Currency = currency; + + public Currency Currency { get; private set; } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Build", "CA1812", Justification = "Compiler dosen't understand dependency injection")] + internal class CurrencyCreateHandler : RequestHandlerBase> + { + private readonly ICurrencyRepository currencyRepository; + private readonly ICurrencyValidator currencyValidator; + + public CurrencyCreateHandler(ILoggingProvider loggingProvider, ICurrencyRepository currencyRepository, ICurrencyValidator currencyValidator) + : base(loggingProvider) + { + this.currencyRepository = currencyRepository; + this.currencyValidator = currencyValidator; + } + + public override async Task> Handle(CurrencyCreateCommand command, CancellationToken cancellationToken) + { + var validationResult = await currencyValidator.ValidateAsync(command.Currency, cancellationToken).ConfigureAwait(false); + + if (validationResult.IsValid == false) + { + return Result.Invalid(validationResult.AsErrors()); + } + + var result = await currencyRepository.SaveAsync(command.Currency).ConfigureAwait(false); + return Result.Success(result); + } + } + } +}