From f60d161ce716c57f12b431be1dd8e5027e1272e0 Mon Sep 17 00:00:00 2001 From: domenkogler Date: Mon, 2 Jul 2018 00:17:43 +0200 Subject: [PATCH] IdentifiedCommand replaced with DuplicateCommandBehavior --- .../Behaviors/DuplicateCommandBehavior.cs | 37 ++++++++ .../Commands/CancelOrderCommand.cs | 4 +- .../Commands/CancelOrderCommandHandler.cs | 11 +-- .../Commands/CreateOrderCommand.cs | 10 +- .../Commands/CreateOrderCommandHandler.cs | 11 +-- .../Commands/CreateOrderDraftCommand.cs | 8 +- .../CreateOrderDraftCommandHandler.cs | 5 +- .../Commands/DuplicateCommandResponse.cs | 30 ++++++ .../Application/Commands/ICommand.cs | 9 ++ .../Application/Commands/IdentifiedCommand.cs | 17 ---- .../Commands/IdentifiedCommandHandler.cs | 64 ------------- .../Application/Commands/ShipOrderCommand.cs | 4 +- .../Commands/ShipOrderCommandHandler.cs | 11 +-- ...CheckoutAcceptedIntegrationEventHandler.cs | 6 +- .../CancelOrderCommandValidator.cs | 1 + .../CreateOrderCommandValidator.cs | 1 + .../Validations/IdentifiedCommandValidator.cs | 13 --- .../Validations/ShipOrderCommandValidator.cs | 1 + .../Controllers/OrdersController.cs | 10 +- .../AutofacModules/MediatorModule.cs | 1 + .../IdentifiedCommandHandlerTest.cs | 91 ------------------- .../Application/NewOrderCommandHandlerTest.cs | 1 + .../Ordering/Application/OrdersWebApiTest.cs | 8 +- 23 files changed, 126 insertions(+), 228 deletions(-) create mode 100644 src/Services/Ordering/Ordering.API/Application/Behaviors/DuplicateCommandBehavior.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/Commands/DuplicateCommandResponse.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/Commands/ICommand.cs delete mode 100644 src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs delete mode 100644 src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs delete mode 100644 src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs delete mode 100644 test/Services/UnitTest/Ordering/Application/IdentifiedCommandHandlerTest.cs diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/DuplicateCommandBehavior.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/DuplicateCommandBehavior.cs new file mode 100644 index 000000000..79541645d --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/DuplicateCommandBehavior.cs @@ -0,0 +1,37 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +using Microsoft.Extensions.Logging; + +namespace Ordering.API.Infrastructure.Behaviors +{ + public class DuplicateCommandBehavior : IPipelineBehavior + where TCommand : ICommand + { + private readonly IMediator _mediator; + private readonly IRequestManager _requestManager; + + public DuplicateCommandBehavior(IMediator mediator, IRequestManager requestManager) + { + _mediator = mediator; + _requestManager = requestManager; + } + + async Task IPipelineBehavior.Handle(TCommand command, CancellationToken cancellationToken, RequestHandlerDelegate next) + { + var alreadyExists = await _requestManager.ExistAsync(command.CommandId); + if (alreadyExists) + { + var duplicateCommand = new DuplicateCommandResponse.DuplicateCommand(command); + return await _mediator.Send(duplicateCommand, cancellationToken); + } + + await _requestManager.CreateRequestForCommandAsync(command.CommandId); + + var response = await next(); + return response; + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs index 0672807f3..a378c3343 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs @@ -4,11 +4,13 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Threading.Tasks; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; namespace Ordering.API.Application.Commands { - public class CancelOrderCommand : IRequest + public class CancelOrderCommand : ICommand, IRequest { + public Guid CommandId { get; set; } [DataMember] public int OrderNumber { get; private set; } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs index a4c4facb8..b476bd21e 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs @@ -38,15 +38,12 @@ namespace Ordering.API.Application.Commands // Use for Idempotency in Command process - public class CancelOrderIdentifiedCommandHandler : IdentifiedCommandHandler + public class CancelOrderDuplicateCommand : DuplicateCommandResponse { - public CancelOrderIdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + protected override Task CreateResponseForDuplicateCommand(CancelOrderCommand command) { - } - - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. + // Ignore duplicate requests for processing order. + return Task.FromResult(true); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs index 1f6e41005..de3a23bfa 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs @@ -18,9 +18,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands // https://msdn.microsoft.com/en-us/library/bb383979.aspx [DataContract] - public class CreateOrderCommand - : IRequest + public class CreateOrderCommand : ICommand, IRequest { + + [DataMember] + public Guid CommandId { get; private set; } + [DataMember] private readonly List _orderItems; @@ -68,10 +71,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands _orderItems = new List(); } - public CreateOrderCommand(List basketItems, string userId, string userName, string city, string street, string state, string country, string zipcode, + public CreateOrderCommand(Guid id, List basketItems, string userId, string userName, string city, string street, string state, string country, string zipcode, string cardNumber, string cardHolderName, DateTime cardExpiration, string cardSecurityNumber, int cardTypeId) : this() { + CommandId = id; _orderItems = basketItems.ToOrderItemsDTO().ToList(); UserId = userId; UserName = userName; diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs index e5f154c0c..548fcf879 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs @@ -47,15 +47,12 @@ // Use for Idempotency in Command process - public class CreateOrderIdentifiedCommandHandler : IdentifiedCommandHandler + public class CreateOrderDuplicateCommand : DuplicateCommandResponse { - public CreateOrderIdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + protected override Task CreateResponseForDuplicateCommand(CreateOrderCommand command) { - } - - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for creating order. + // Ignore duplicate requests for creating order. + return Task.FromResult(true); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs index 1d3d52c63..c276308aa 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs @@ -10,15 +10,17 @@ using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Comma namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands { - public class CreateOrderDraftCommand : IRequest + public class CreateOrderDraftCommand : ICommand, IRequest { - + public Guid CommandId { get; } + public string BuyerId { get; private set; } public IEnumerable Items { get; private set; } - public CreateOrderDraftCommand(string buyerId, IEnumerable items) + public CreateOrderDraftCommand(Guid id, string buyerId, IEnumerable items) { + CommandId = id; BuyerId = buyerId; Items = items; } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs index 2c315248b..717ed5673 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs @@ -10,7 +10,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; - using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; // Regular CommandHandler public class CreateOrderDraftCommandHandler @@ -44,14 +43,14 @@ public class OrderDraftDTO { - public IEnumerable OrderItems { get; set; } + public IEnumerable OrderItems { get; set; } public decimal Total { get; set; } public static OrderDraftDTO FromOrder(Order order) { return new OrderDraftDTO() { - OrderItems = order.OrderItems.Select(oi => new OrderItemDTO + OrderItems = order.OrderItems.Select(oi => new CreateOrderCommand.OrderItemDTO { Discount = oi.GetCurrentDiscount(), ProductId = oi.ProductId, diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/DuplicateCommandResponse.cs b/src/Services/Ordering/Ordering.API/Application/Commands/DuplicateCommandResponse.cs new file mode 100644 index 000000000..1fbb84ae1 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/DuplicateCommandResponse.cs @@ -0,0 +1,30 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; + +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +{ + public abstract class DuplicateCommandResponse : IRequestHandler.DuplicateCommand, TResponse> + { + public class DuplicateCommand : IRequest + { + public DuplicateCommand(TCommand command) + { + Command = command; + } + + public TCommand Command { get; } + } + + /// + /// Creates the result value to return if a previous request was found + /// + /// + protected abstract Task CreateResponseForDuplicateCommand(TCommand command); + + Task IRequestHandler, TResponse>.Handle(DuplicateCommand request, CancellationToken cancellationToken) + { + return CreateResponseForDuplicateCommand(request.Command); + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ICommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ICommand.cs new file mode 100644 index 000000000..b85b90f8c --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/ICommand.cs @@ -0,0 +1,9 @@ +using System; + +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +{ + public interface ICommand + { + Guid CommandId { get; } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs deleted file mode 100644 index 9486cd143..000000000 --- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediatR; -using System; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands -{ - public class IdentifiedCommand : IRequest - where T : IRequest - { - public T Command { get; } - public Guid Id { get; } - public IdentifiedCommand(T command, Guid id) - { - Command = command; - Id = id; - } - } -} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs deleted file mode 100644 index f00ea44c8..000000000 --- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands -{ - /// - /// Provides a base implementation for handling duplicate request and ensuring idempotent updates, in the cases where - /// a requestid sent by client is used to detect duplicate requests. - /// - /// Type of the command handler that performs the operation if request is not duplicated - /// Return value of the inner command handler - public class IdentifiedCommandHandler : IRequestHandler, R> - where T : IRequest - { - private readonly IMediator _mediator; - private readonly IRequestManager _requestManager; - - public IdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) - { - _mediator = mediator; - _requestManager = requestManager; - } - - /// - /// Creates the result value to return if a previous request was found - /// - /// - protected virtual R CreateResultForDuplicateRequest() - { - return default(R); - } - - /// - /// This method handles the command. It just ensures that no other request exists with the same ID, and if this is the case - /// just enqueues the original inner command. - /// - /// IdentifiedCommand which contains both original command & request ID - /// Return value of inner command or default value if request same ID was found - public async Task Handle(IdentifiedCommand message, CancellationToken cancellationToken) - { - var alreadyExists = await _requestManager.ExistAsync(message.Id); - if (alreadyExists) - { - return CreateResultForDuplicateRequest(); - } - else - { - await _requestManager.CreateRequestForCommandAsync(message.Id); - try - { - // Send the embeded business command to mediator so it runs its related CommandHandler - var result = await _mediator.Send(message.Command); - return result; - } - catch - { - return default(R); - } - } - } - } -} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs index 08f37007d..e7aba489e 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs @@ -4,11 +4,13 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Threading.Tasks; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; namespace Ordering.API.Application.Commands { - public class ShipOrderCommand : IRequest + public class ShipOrderCommand : ICommand, IRequest { + public Guid CommandId { get; set; } [DataMember] public int OrderNumber { get; private set; } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs index b4a6ac26d..d5e9416aa 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs @@ -38,15 +38,12 @@ namespace Ordering.API.Application.Commands // Use for Idempotency in Command process - public class ShipOrderIdentifiedCommandHandler : IdentifiedCommandHandler + public class ShipOrderDuplicateCommand : DuplicateCommandResponse { - public ShipOrderIdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + protected override Task CreateResponseForDuplicateCommand(ShipOrderCommand command) { - } - - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. + // Ignore duplicate requests for creating order. + return Task.FromResult(true); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs index f46c5683c..f754a4449 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs @@ -41,13 +41,13 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling if (eventMsg.RequestId != Guid.Empty) { - var createOrderCommand = new CreateOrderCommand(eventMsg.Basket.Items, eventMsg.UserId, eventMsg.UserName, eventMsg.City, eventMsg.Street, + var createOrderCommand = new CreateOrderCommand(eventMsg.RequestId, eventMsg.Basket.Items, eventMsg.UserId, eventMsg.UserName, eventMsg.City, eventMsg.Street, eventMsg.State, eventMsg.Country, eventMsg.ZipCode, eventMsg.CardNumber, eventMsg.CardHolderName, eventMsg.CardExpiration, eventMsg.CardSecurityNumber, eventMsg.CardTypeId); - var requestCreateOrder = new IdentifiedCommand(createOrderCommand, eventMsg.RequestId); - result = await _mediator.Send(requestCreateOrder); + //var requestCreateOrder = new IdentifiedCommand(createOrderCommand, eventMsg.RequestId); + result = await _mediator.Send(createOrderCommand); } _logger.CreateLogger(nameof(UserCheckoutAcceptedIntegrationEventHandler)) diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs index 5c619586f..d8e786c8c 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs @@ -11,6 +11,7 @@ namespace Ordering.API.Application.Validations { public CancelOrderCommandValidator() { + RuleFor(command => command.CommandId).NotEmpty(); RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); } } diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs index e6bbdd4d9..8214328ba 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs @@ -11,6 +11,7 @@ namespace Ordering.API.Application.Validations { public CreateOrderCommandValidator() { + RuleFor(command => command.CommandId).NotEmpty(); RuleFor(command => command.City).NotEmpty(); RuleFor(command => command.Street).NotEmpty(); RuleFor(command => command.State).NotEmpty(); diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs deleted file mode 100644 index 84ae48835..000000000 --- a/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; - -namespace Ordering.API.Application.Validations -{ - public class IdentifiedCommandValidator : AbstractValidator> - { - public IdentifiedCommandValidator() - { - RuleFor(command => command.Id).NotEmpty(); - } - } -} diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs index 72a16d319..9bc9a3126 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs @@ -11,6 +11,7 @@ namespace Ordering.API.Application.Validations { public ShipOrderCommandValidator() { + RuleFor(command => command.CommandId).NotEmpty(); RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); } } diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index 5542caf11..12ef768d0 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -38,8 +38,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers bool commandResult = false; if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) { - var requestCancelOrder = new IdentifiedCommand(command, guid); - commandResult = await _mediator.Send(requestCancelOrder); + command.CommandId = guid; + //var requestCancelOrder = new IdentifiedCommand(command, guid); + commandResult = await _mediator.Send(command); } return commandResult ? (IActionResult)Ok() : (IActionResult)BadRequest(); @@ -55,8 +56,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers bool commandResult = false; if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) { - var requestShipOrder = new IdentifiedCommand(command, guid); - commandResult = await _mediator.Send(requestShipOrder); + command.CommandId = guid; + //var requestShipOrder = new IdentifiedCommand(command, guid); + commandResult = await _mediator.Send(command); } return commandResult ? (IActionResult)Ok() : (IActionResult)BadRequest(); diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs index e9e7b4395..41c7a4774 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs @@ -42,6 +42,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>)); builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>)); + builder.RegisterGeneric(typeof(DuplicateCommandBehavior<,>)).As(typeof(IPipelineBehavior<,>)); } } diff --git a/test/Services/UnitTest/Ordering/Application/IdentifiedCommandHandlerTest.cs b/test/Services/UnitTest/Ordering/Application/IdentifiedCommandHandlerTest.cs deleted file mode 100644 index e0f861017..000000000 --- a/test/Services/UnitTest/Ordering/Application/IdentifiedCommandHandlerTest.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace UnitTest.Ordering.Application -{ - using global::Ordering.API.Application.Models; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; - using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; - using Moq; - using System.Collections; - using System.Collections.Generic; - using System.Threading.Tasks; - using Xunit; - public class IdentifiedCommandHandlerTest - { - private readonly Mock _requestManager; - private readonly Mock _mediator; - - public IdentifiedCommandHandlerTest() - { - _requestManager = new Mock(); - _mediator = new Mock(); - } - - [Fact] - public async Task Handler_sends_command_when_order_no_exists() - { - // Arrange - var fakeGuid = Guid.NewGuid(); - var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); - - _requestManager.Setup(x => x.ExistAsync(It.IsAny())) - .Returns(Task.FromResult(false)); - - _mediator.Setup(x => x.Send(It.IsAny>(),default(System.Threading.CancellationToken))) - .Returns(Task.FromResult(true)); - - //Act - var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object); - var cltToken = new System.Threading.CancellationToken(); - var result = await handler.Handle(fakeOrderCmd, cltToken); - - //Assert - Assert.True(result); - _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Once()); - } - - [Fact] - public async Task Handler_sends_no_command_when_order_already_exists() - { - // Arrange - var fakeGuid = Guid.NewGuid(); - var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); - - _requestManager.Setup(x => x.ExistAsync(It.IsAny())) - .Returns(Task.FromResult(true)); - - _mediator.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) - .Returns(Task.FromResult(true)); - - //Act - var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object); - var cltToken = new System.Threading.CancellationToken(); - var result = await handler.Handle(fakeOrderCmd, cltToken); - - //Assert - Assert.False(result); - _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Never()); - } - - private CreateOrderCommand FakeOrderRequest(Dictionary args = null) - { - return new CreateOrderCommand( - new List(), - userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, - userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, - city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, - street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, - state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, - country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, - zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, - cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", - cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, - cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", - cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", - cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); - } - } -} diff --git a/test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs b/test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs index 7fe02017b..4c79a66e6 100644 --- a/test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs +++ b/test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs @@ -76,6 +76,7 @@ namespace UnitTest.Ordering.Application private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary args = null) { return new CreateOrderCommand( + Guid.NewGuid(), new List(), userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, diff --git a/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs b/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs index 516f9ba54..1a8ff1622 100644 --- a/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs +++ b/test/Services/UnitTest/Ordering/Application/OrdersWebApiTest.cs @@ -31,7 +31,7 @@ namespace UnitTest.Ordering.Application public async Task Create_order_with_requestId_success() { //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) + _mediatorMock.Setup(x => x.Send(It.IsAny(), default(CancellationToken))) .Returns(Task.FromResult(true)); //Act @@ -47,7 +47,7 @@ namespace UnitTest.Ordering.Application public async Task Cancel_order_bad_request() { //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) + _mediatorMock.Setup(x => x.Send(It.IsAny(), default(CancellationToken))) .Returns(Task.FromResult(true)); //Act @@ -62,7 +62,7 @@ namespace UnitTest.Ordering.Application public async Task Ship_order_with_requestId_success() { //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + _mediatorMock.Setup(x => x.Send(It.IsAny(), default(System.Threading.CancellationToken))) .Returns(Task.FromResult(true)); //Act @@ -78,7 +78,7 @@ namespace UnitTest.Ordering.Application public async Task Ship_order_bad_request() { //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + _mediatorMock.Setup(x => x.Send(It.IsAny(), default(System.Threading.CancellationToken))) .Returns(Task.FromResult(true)); //Act