Immutable commands - wip

This commit is contained in:
etomas 2017-02-27 17:52:14 +01:00
parent b4162035f9
commit 67ab1159df
5 changed files with 82 additions and 61 deletions

View File

@ -11,27 +11,25 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
{ {
private readonly List<OrderItemDTO> _orderItems; private readonly List<OrderItemDTO> _orderItems;
public string City { get; set; } public string City { get; private set; }
public string Street { get; set; } public string Street { get; private set; }
public string State { get; set; } public string State { get; private set; }
public string Country { get; set; } public string Country { get; private set; }
public string ZipCode { get; set; } public string ZipCode { get; private set; }
public string CardNumber { get; set; } public string CardNumber { get; private set; }
public string CardHolderName { get; set; } public string CardHolderName { get; private set; }
public DateTime CardExpiration { get; set; } public DateTime CardExpiration { get; private set; }
public string CardSecurityNumber { get; set; } public string CardSecurityNumber { get; private set; }
public int CardTypeId { get; set; } public int CardTypeId { get; private set; }
public string BuyerIdentityGuid { get; set; }
public IEnumerable<OrderItemDTO> OrderItems => _orderItems; public IEnumerable<OrderItemDTO> OrderItems => _orderItems;
@ -45,6 +43,21 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
_orderItems = new List<OrderItemDTO>(); _orderItems = new List<OrderItemDTO>();
} }
public CreateOrderCommand(string city, string street, string state, string country, string zipcode,
string cardNumber, string cardHolderName, DateTime cardExpiration,
string cardSecurityNumber, int cardTypeId) : this()
{
City = city;
Street = street;
State = state;
Country = country;
ZipCode = zipcode;
CardNumber = cardNumber;
CardHolderName = cardHolderName;
CardSecurityNumber = cardSecurityNumber;
CardTypeId = cardTypeId;
}
public class OrderItemDTO public class OrderItemDTO
{ {

View File

@ -3,6 +3,7 @@
using Domain.AggregatesModel.BuyerAggregate; using Domain.AggregatesModel.BuyerAggregate;
using Domain.AggregatesModel.OrderAggregate; using Domain.AggregatesModel.OrderAggregate;
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,12 +12,14 @@
{ {
private readonly IBuyerRepository<Buyer> _buyerRepository; private readonly IBuyerRepository<Buyer> _buyerRepository;
private readonly IOrderRepository<Order> _orderRepository; private readonly IOrderRepository<Order> _orderRepository;
private readonly IIdentityService _identityService;
// Using DI to inject infrastructure persistence Repositories // Using DI to inject infrastructure persistence Repositories
public CreateOrderCommandHandler(IBuyerRepository<Buyer> buyerRepository, IOrderRepository<Order> orderRepository) public CreateOrderCommandHandler(IBuyerRepository<Buyer> buyerRepository, IOrderRepository<Order> orderRepository, IIdentityService identityService)
{ {
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
} }
public async Task<bool> Handle(CreateOrderCommand message) public async Task<bool> Handle(CreateOrderCommand message)
@ -26,14 +29,17 @@
// methods and constructor so validations, invariants and business logic // methods and constructor so validations, invariants and business logic
// make sure that consistency is preserved across the whole aggregate // make sure that consistency is preserved across the whole aggregate
var buyer = await _buyerRepository.FindAsync(message.BuyerIdentityGuid); var cardTypeId = message.CardTypeId != 0 ? message.CardTypeId : 1;
var buyerGuid = _identityService.GetUserIdentity();
var buyer = await _buyerRepository.FindAsync(buyerGuid);
if (buyer == null) if (buyer == null)
{ {
buyer = new Buyer(message.BuyerIdentityGuid); buyer = new Buyer(buyerGuid);
} }
var payment = buyer.AddPaymentMethod(message.CardTypeId, var payment = buyer.AddPaymentMethod(cardTypeId,
$"Payment Method on {DateTime.UtcNow}", $"Payment Method on {DateTime.UtcNow}",
message.CardNumber, message.CardNumber,
message.CardSecurityNumber, message.CardSecurityNumber,

View File

@ -30,13 +30,6 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
[HttpPost] [HttpPost]
public async Task<IActionResult> CreateOrder([FromBody]CreateOrderCommand createOrderCommand) public async Task<IActionResult> CreateOrder([FromBody]CreateOrderCommand createOrderCommand)
{ {
if (createOrderCommand.CardTypeId == 0)
{
createOrderCommand.CardTypeId = 1;
}
createOrderCommand.BuyerIdentityGuid = _identityService.GetUserIdentity();
var result = await _mediator.SendAsync(createOrderCommand); var result = await _mediator.SendAsync(createOrderCommand);
if (result) if (result)
{ {

View File

@ -65,19 +65,18 @@
string BuildOrder() string BuildOrder()
{ {
var order = new CreateOrderCommand() var order = new CreateOrderCommand(
{ cardExpiration: DateTime.UtcNow.AddYears(1),
CardExpiration = DateTime.UtcNow.AddYears(1), cardNumber: "5145-555-5555",
CardNumber = "5145-555-5555", cardHolderName: "Jhon Senna",
CardHolderName = "Jhon Senna", cardSecurityNumber: "232",
CardSecurityNumber = "232", cardTypeId: 1,
CardTypeId = 1, city: "Redmon",
City = "Redmon", country: "USA",
Country = "USA", state: "WA",
State = "WA", street: "One way",
Street = "One way", zipcode: "zipcode"
ZipCode = "zipcode", );
};
order.AddOrderItem(new OrderItemDTO() order.AddOrderItem(new OrderItemDTO()
{ {
@ -92,19 +91,18 @@
} }
string BuildOrderWithInvalidExperationTime() string BuildOrderWithInvalidExperationTime()
{ {
var order = new CreateOrderCommand() var order = new CreateOrderCommand(
{ cardExpiration: DateTime.UtcNow.AddYears(-1),
CardExpiration = DateTime.UtcNow.AddYears(-1), cardNumber: "5145-555-5555",
CardNumber = "5145-555-5555", cardHolderName: "Jhon Senna",
CardHolderName = "Jhon Senna", cardSecurityNumber: "232",
CardSecurityNumber = "232", cardTypeId: 1,
CardTypeId = 1, city: "Redmon",
City = "Redmon", country: "USA",
Country = "USA", state: "WA",
State = "WA", street: "One way",
Street = "One way", zipcode: "zipcode"
ZipCode = "zipcode" );
};
return JsonConvert.SerializeObject(order); return JsonConvert.SerializeObject(order);
} }

View File

@ -1,4 +1,5 @@
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Moq; using Moq;
@ -13,19 +14,23 @@ namespace UnitTest.Ordering.Application
{ {
private readonly Mock<IBuyerRepository<Buyer>> _buyerRepositoryMock; private readonly Mock<IBuyerRepository<Buyer>> _buyerRepositoryMock;
private readonly Mock<IOrderRepository<Order>> _orderRepositoryMock; private readonly Mock<IOrderRepository<Order>> _orderRepositoryMock;
private readonly Mock<IIdentityService> _identityServiceMock;
public NewOrderRequestHandlerTest() public NewOrderRequestHandlerTest()
{ {
_buyerRepositoryMock = new Mock<IBuyerRepository<Buyer>>(); _buyerRepositoryMock = new Mock<IBuyerRepository<Buyer>>();
_orderRepositoryMock = new Mock<IOrderRepository<Order>>(); _orderRepositoryMock = new Mock<IOrderRepository<Order>>();
_identityServiceMock = new Mock<IIdentityService>();
} }
[Fact] [Fact]
public async Task Handle_returns_true_when_order_is_persisted_succesfully() public async Task Handle_returns_true_when_order_is_persisted_succesfully()
{ {
var buyerId = "1234";
// Arrange // Arrange
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().BuyerIdentityGuid)) _buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
.Returns(Task.FromResult<Buyer>(FakeBuyer())); .Returns(Task.FromResult<Buyer>(FakeBuyer()));
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) _buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
@ -37,8 +42,9 @@ namespace UnitTest.Ordering.Application
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken))) _orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
.Returns(Task.FromResult(1)); .Returns(Task.FromResult(1));
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
//Act //Act
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object); var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
var result = await handler.Handle(FakeOrderRequestWithBuyer()); var result = await handler.Handle(FakeOrderRequestWithBuyer());
//Assert //Assert
@ -48,7 +54,8 @@ namespace UnitTest.Ordering.Application
[Fact] [Fact]
public async Task Handle_return_false_if_order_is_not_persisted() public async Task Handle_return_false_if_order_is_not_persisted()
{ {
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().BuyerIdentityGuid)) var buyerId = "1234";
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
.Returns(Task.FromResult<Buyer>(FakeBuyer())); .Returns(Task.FromResult<Buyer>(FakeBuyer()));
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) _buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
@ -57,9 +64,10 @@ namespace UnitTest.Ordering.Application
_orderRepositoryMock.Setup(or => or.Add(FakeOrder())).Returns(FakeOrder()); _orderRepositoryMock.Setup(or => or.Add(FakeOrder())).Returns(FakeOrder());
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken))) _orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
.Returns(Task.FromResult(0)); .Returns(Task.FromResult(0));
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
//Act //Act
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object); var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
var result = await handler.Handle(FakeOrderRequestWithBuyer()); var result = await handler.Handle(FakeOrderRequestWithBuyer());
//Assert //Assert
@ -78,14 +86,17 @@ namespace UnitTest.Ordering.Application
private CreateOrderCommand FakeOrderRequestWithBuyer() private CreateOrderCommand FakeOrderRequestWithBuyer()
{ {
return new CreateOrderCommand return new CreateOrderCommand(
{ city: null,
BuyerIdentityGuid = "1234", street: null,
CardNumber = "1234", state: null,
CardExpiration = DateTime.Now.AddYears(1), country: null,
CardSecurityNumber = "123", zipcode: null,
CardHolderName = "XXX" cardNumber: "1234",
}; cardExpiration: DateTime.Now.AddYears(1),
cardSecurityNumber: "123",
cardHolderName: "XXX",
cardTypeId: 0);
} }
} }
} }