@ -1,91 +1,79 @@ | |||||
using System; | |||||
namespace UnitTest.Ordering.Application; | |||||
namespace UnitTest.Ordering.Application | |||||
public class IdentifiedCommandHandlerTest | |||||
{ | { | ||||
using global::Ordering.API.Application.Models; | |||||
using MediatR; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; | |||||
using Microsoft.Extensions.Logging; | |||||
using Moq; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
public class IdentifiedCommandHandlerTest | |||||
{ | |||||
private readonly Mock<IRequestManager> _requestManager; | |||||
private readonly Mock<IMediator> _mediator; | |||||
private readonly Mock<ILogger<IdentifiedCommandHandler<CreateOrderCommand, bool>>> _loggerMock; | |||||
private readonly Mock<IRequestManager> _requestManager; | |||||
private readonly Mock<IMediator> _mediator; | |||||
private readonly Mock<ILogger<IdentifiedCommandHandler<CreateOrderCommand, bool>>> _loggerMock; | |||||
public IdentifiedCommandHandlerTest() | |||||
{ | |||||
_requestManager = new Mock<IRequestManager>(); | |||||
_mediator = new Mock<IMediator>(); | |||||
_loggerMock = new Mock<ILogger<IdentifiedCommandHandler<CreateOrderCommand, bool>>>(); | |||||
} | |||||
public IdentifiedCommandHandlerTest() | |||||
{ | |||||
_requestManager = new Mock<IRequestManager>(); | |||||
_mediator = new Mock<IMediator>(); | |||||
_loggerMock = new Mock<ILogger<IdentifiedCommandHandler<CreateOrderCommand, bool>>>(); | |||||
} | |||||
[Fact] | |||||
public async Task Handler_sends_command_when_order_no_exists() | |||||
{ | |||||
// Arrange | |||||
var fakeGuid = Guid.NewGuid(); | |||||
var fakeOrderCmd = new IdentifiedCommand<CreateOrderCommand, bool>(FakeOrderRequest(), fakeGuid); | |||||
[Fact] | |||||
public async Task Handler_sends_command_when_order_no_exists() | |||||
{ | |||||
// Arrange | |||||
var fakeGuid = Guid.NewGuid(); | |||||
var fakeOrderCmd = new IdentifiedCommand<CreateOrderCommand, bool>(FakeOrderRequest(), fakeGuid); | |||||
_requestManager.Setup(x => x.ExistAsync(It.IsAny<Guid>())) | |||||
.Returns(Task.FromResult(false)); | |||||
_requestManager.Setup(x => x.ExistAsync(It.IsAny<Guid>())) | |||||
.Returns(Task.FromResult(false)); | |||||
_mediator.Setup(x => x.Send(It.IsAny<IRequest<bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
_mediator.Setup(x => x.Send(It.IsAny<IRequest<bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var handler = new IdentifiedCommandHandler<CreateOrderCommand, bool>(_mediator.Object, _requestManager.Object, _loggerMock.Object); | |||||
var cltToken = new System.Threading.CancellationToken(); | |||||
var result = await handler.Handle(fakeOrderCmd, cltToken); | |||||
//Act | |||||
var handler = new IdentifiedCommandHandler<CreateOrderCommand, bool>(_mediator.Object, _requestManager.Object, _loggerMock.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<IRequest<bool>>(), default(System.Threading.CancellationToken)), Times.Once()); | |||||
} | |||||
//Assert | |||||
Assert.True(result); | |||||
_mediator.Verify(x => x.Send(It.IsAny<IRequest<bool>>(), 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<CreateOrderCommand, bool>(FakeOrderRequest(), fakeGuid); | |||||
[Fact] | |||||
public async Task Handler_sends_no_command_when_order_already_exists() | |||||
{ | |||||
// Arrange | |||||
var fakeGuid = Guid.NewGuid(); | |||||
var fakeOrderCmd = new IdentifiedCommand<CreateOrderCommand, bool>(FakeOrderRequest(), fakeGuid); | |||||
_requestManager.Setup(x => x.ExistAsync(It.IsAny<Guid>())) | |||||
.Returns(Task.FromResult(true)); | |||||
_requestManager.Setup(x => x.ExistAsync(It.IsAny<Guid>())) | |||||
.Returns(Task.FromResult(true)); | |||||
_mediator.Setup(x => x.Send(It.IsAny<IRequest<bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
_mediator.Setup(x => x.Send(It.IsAny<IRequest<bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var handler = new IdentifiedCommandHandler<CreateOrderCommand, bool>(_mediator.Object, _requestManager.Object, _loggerMock.Object); | |||||
var cltToken = new System.Threading.CancellationToken(); | |||||
var result = await handler.Handle(fakeOrderCmd, cltToken); | |||||
//Act | |||||
var handler = new IdentifiedCommandHandler<CreateOrderCommand, bool>(_mediator.Object, _requestManager.Object, _loggerMock.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<IRequest<bool>>(), default(System.Threading.CancellationToken)), Times.Never()); | |||||
} | |||||
//Assert | |||||
Assert.False(result); | |||||
_mediator.Verify(x => x.Send(It.IsAny<IRequest<bool>>(), default(System.Threading.CancellationToken)), Times.Never()); | |||||
} | |||||
private CreateOrderCommand FakeOrderRequest(Dictionary<string, object> args = null) | |||||
{ | |||||
return new CreateOrderCommand( | |||||
new List<BasketItem>(), | |||||
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); | |||||
} | |||||
private CreateOrderCommand FakeOrderRequest(Dictionary<string, object> args = null) | |||||
{ | |||||
return new CreateOrderCommand( | |||||
new List<BasketItem>(), | |||||
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); | |||||
} | } | ||||
} | } |
@ -1,97 +1,83 @@ | |||||
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.OrderAggregate; | |||||
using Moq; | |||||
using System; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents; | |||||
namespace UnitTest.Ordering.Application; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||||
namespace UnitTest.Ordering.Application | |||||
public class NewOrderRequestHandlerTest | |||||
{ | { | ||||
using global::Ordering.API.Application.IntegrationEvents; | |||||
using global::Ordering.API.Application.Models; | |||||
using MediatR; | |||||
using Microsoft.Extensions.Logging; | |||||
using System.Collections.Generic; | |||||
using Xunit; | |||||
public class NewOrderRequestHandlerTest | |||||
private readonly Mock<IOrderRepository> _orderRepositoryMock; | |||||
private readonly Mock<IIdentityService> _identityServiceMock; | |||||
private readonly Mock<IMediator> _mediator; | |||||
private readonly Mock<IOrderingIntegrationEventService> _orderingIntegrationEventService; | |||||
public NewOrderRequestHandlerTest() | |||||
{ | |||||
_orderRepositoryMock = new Mock<IOrderRepository>(); | |||||
_identityServiceMock = new Mock<IIdentityService>(); | |||||
_orderingIntegrationEventService = new Mock<IOrderingIntegrationEventService>(); | |||||
_mediator = new Mock<IMediator>(); | |||||
} | |||||
[Fact] | |||||
public async Task Handle_return_false_if_order_is_not_persisted() | |||||
{ | |||||
var buyerId = "1234"; | |||||
var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary<string, object> | |||||
{ ["cardExpiration"] = DateTime.Now.AddYears(1) }); | |||||
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>())) | |||||
.Returns(Task.FromResult<Order>(FakeOrder())); | |||||
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) | |||||
.Returns(Task.FromResult(1)); | |||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId); | |||||
var LoggerMock = new Mock<ILogger<CreateOrderCommandHandler>>(); | |||||
//Act | |||||
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderingIntegrationEventService.Object, _orderRepositoryMock.Object, _identityServiceMock.Object, LoggerMock.Object); | |||||
var cltToken = new System.Threading.CancellationToken(); | |||||
var result = await handler.Handle(fakeOrderCmd, cltToken); | |||||
//Assert | |||||
Assert.False(result); | |||||
} | |||||
[Fact] | |||||
public void Handle_throws_exception_when_no_buyerId() | |||||
{ | |||||
//Assert | |||||
Assert.Throws<ArgumentNullException>(() => new Buyer(string.Empty, string.Empty)); | |||||
} | |||||
private Buyer FakeBuyer() | |||||
{ | |||||
return new Buyer(Guid.NewGuid().ToString(), "1"); | |||||
} | |||||
private Order FakeOrder() | |||||
{ | |||||
return new Order("1", "fakeName", new Address("street", "city", "state", "country", "zipcode"), 1, "12", "111", "fakeName", DateTime.Now.AddYears(1)); | |||||
} | |||||
private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary<string, object> args = null) | |||||
{ | { | ||||
private readonly Mock<IOrderRepository> _orderRepositoryMock; | |||||
private readonly Mock<IIdentityService> _identityServiceMock; | |||||
private readonly Mock<IMediator> _mediator; | |||||
private readonly Mock<IOrderingIntegrationEventService> _orderingIntegrationEventService; | |||||
public NewOrderRequestHandlerTest() | |||||
{ | |||||
_orderRepositoryMock = new Mock<IOrderRepository>(); | |||||
_identityServiceMock = new Mock<IIdentityService>(); | |||||
_orderingIntegrationEventService = new Mock<IOrderingIntegrationEventService>(); | |||||
_mediator = new Mock<IMediator>(); | |||||
} | |||||
[Fact] | |||||
public async Task Handle_return_false_if_order_is_not_persisted() | |||||
{ | |||||
var buyerId = "1234"; | |||||
var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary<string, object> | |||||
{ ["cardExpiration"] = DateTime.Now.AddYears(1) }); | |||||
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>())) | |||||
.Returns(Task.FromResult<Order>(FakeOrder())); | |||||
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) | |||||
.Returns(Task.FromResult(1)); | |||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId); | |||||
var LoggerMock = new Mock<ILogger<CreateOrderCommandHandler>>(); | |||||
//Act | |||||
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderingIntegrationEventService.Object, _orderRepositoryMock.Object, _identityServiceMock.Object, LoggerMock.Object); | |||||
var cltToken = new System.Threading.CancellationToken(); | |||||
var result = await handler.Handle(fakeOrderCmd, cltToken); | |||||
//Assert | |||||
Assert.False(result); | |||||
} | |||||
[Fact] | |||||
public void Handle_throws_exception_when_no_buyerId() | |||||
{ | |||||
//Assert | |||||
Assert.Throws<ArgumentNullException>(() => new Buyer(string.Empty, string.Empty)); | |||||
} | |||||
private Buyer FakeBuyer() | |||||
{ | |||||
return new Buyer(Guid.NewGuid().ToString(), "1"); | |||||
} | |||||
private Order FakeOrder() | |||||
{ | |||||
return new Order("1", "fakeName", new Address("street", "city", "state", "country", "zipcode"), 1, "12", "111", "fakeName", DateTime.Now.AddYears(1)); | |||||
} | |||||
private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary<string, object> args = null) | |||||
{ | |||||
return new CreateOrderCommand( | |||||
new List<BasketItem>(), | |||||
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); | |||||
} | |||||
return new CreateOrderCommand( | |||||
new List<BasketItem>(), | |||||
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); | |||||
} | } | ||||
} | } |
@ -1,148 +1,134 @@ | |||||
using MediatR; | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||||
namespace UnitTest.Ordering.Application; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; | using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; | ||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; | |||||
using Microsoft.Extensions.Logging; | |||||
using Moq; | |||||
using Ordering.API.Application.Commands; | |||||
using System; | |||||
using System.Linq; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
namespace UnitTest.Ordering.Application | |||||
public class OrdersWebApiTest | |||||
{ | { | ||||
public class OrdersWebApiTest | |||||
private readonly Mock<IMediator> _mediatorMock; | |||||
private readonly Mock<IOrderQueries> _orderQueriesMock; | |||||
private readonly Mock<IIdentityService> _identityServiceMock; | |||||
private readonly Mock<ILogger<OrdersController>> _loggerMock; | |||||
public OrdersWebApiTest() | |||||
{ | |||||
_mediatorMock = new Mock<IMediator>(); | |||||
_orderQueriesMock = new Mock<IOrderQueries>(); | |||||
_identityServiceMock = new Mock<IIdentityService>(); | |||||
_loggerMock = new Mock<ILogger<OrdersController>>(); | |||||
} | |||||
[Fact] | |||||
public async Task Cancel_order_with_requestId_success() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CancelOrderCommand, bool>>(), default(CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Cancel_order_bad_request() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CancelOrderCommand, bool>>(), default(CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), String.Empty) as BadRequestResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); | |||||
} | |||||
[Fact] | |||||
public async Task Ship_order_with_requestId_success() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<ShipOrderCommand, bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Ship_order_bad_request() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CreateOrderCommand, bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), String.Empty) as BadRequestResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); | |||||
} | |||||
[Fact] | |||||
public async Task Get_orders_success() | |||||
{ | |||||
//Arrange | |||||
var fakeDynamicResult = Enumerable.Empty<OrderSummary>(); | |||||
_identityServiceMock.Setup(x => x.GetUserIdentity()) | |||||
.Returns(Guid.NewGuid().ToString()); | |||||
_orderQueriesMock.Setup(x => x.GetOrdersFromUserAsync(Guid.NewGuid())) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.GetOrdersAsync(); | |||||
//Assert | |||||
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Get_order_success() | |||||
{ | { | ||||
private readonly Mock<IMediator> _mediatorMock; | |||||
private readonly Mock<IOrderQueries> _orderQueriesMock; | |||||
private readonly Mock<IIdentityService> _identityServiceMock; | |||||
private readonly Mock<ILogger<OrdersController>> _loggerMock; | |||||
public OrdersWebApiTest() | |||||
{ | |||||
_mediatorMock = new Mock<IMediator>(); | |||||
_orderQueriesMock = new Mock<IOrderQueries>(); | |||||
_identityServiceMock = new Mock<IIdentityService>(); | |||||
_loggerMock = new Mock<ILogger<OrdersController>>(); | |||||
} | |||||
[Fact] | |||||
public async Task Cancel_order_with_requestId_success() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CancelOrderCommand, bool>>(), default(CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Cancel_order_bad_request() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CancelOrderCommand, bool>>(), default(CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), String.Empty) as BadRequestResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); | |||||
} | |||||
[Fact] | |||||
public async Task Ship_order_with_requestId_success() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<ShipOrderCommand, bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Ship_order_bad_request() | |||||
{ | |||||
//Arrange | |||||
_mediatorMock.Setup(x => x.Send(It.IsAny<IdentifiedCommand<CreateOrderCommand, bool>>(), default(System.Threading.CancellationToken))) | |||||
.Returns(Task.FromResult(true)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), String.Empty) as BadRequestResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); | |||||
} | |||||
[Fact] | |||||
public async Task Get_orders_success() | |||||
{ | |||||
//Arrange | |||||
var fakeDynamicResult = Enumerable.Empty<OrderSummary>(); | |||||
_identityServiceMock.Setup(x => x.GetUserIdentity()) | |||||
.Returns(Guid.NewGuid().ToString()); | |||||
_orderQueriesMock.Setup(x => x.GetOrdersFromUserAsync(Guid.NewGuid())) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.GetOrdersAsync(); | |||||
//Assert | |||||
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Get_order_success() | |||||
{ | |||||
//Arrange | |||||
var fakeOrderId = 123; | |||||
var fakeDynamicResult = new Order(); | |||||
_orderQueriesMock.Setup(x => x.GetOrderAsync(It.IsAny<int>())) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.GetOrderAsync(fakeOrderId) as OkObjectResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Get_cardTypes_success() | |||||
{ | |||||
//Arrange | |||||
var fakeDynamicResult = Enumerable.Empty<CardType>(); | |||||
_orderQueriesMock.Setup(x => x.GetCardTypesAsync()) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.GetCardTypesAsync(); | |||||
//Assert | |||||
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
//Arrange | |||||
var fakeOrderId = 123; | |||||
var fakeDynamicResult = new Order(); | |||||
_orderQueriesMock.Setup(x => x.GetOrderAsync(It.IsAny<int>())) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.GetOrderAsync(fakeOrderId) as OkObjectResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
[Fact] | |||||
public async Task Get_cardTypes_success() | |||||
{ | |||||
//Arrange | |||||
var fakeDynamicResult = Enumerable.Empty<CardType>(); | |||||
_orderQueriesMock.Setup(x => x.GetCardTypesAsync()) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); | |||||
var actionResult = await orderController.GetCardTypesAsync(); | |||||
//Assert | |||||
Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | } | ||||
} | } |
@ -1,48 +1,46 @@ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||||
using System; | |||||
namespace UnitTest.Ordering; | |||||
namespace UnitTest.Ordering | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||||
public class AddressBuilder | |||||
{ | { | ||||
public class AddressBuilder | |||||
public Address Build() | |||||
{ | { | ||||
public Address Build() | |||||
{ | |||||
return new Address("street", "city", "state", "country", "zipcode"); | |||||
} | |||||
return new Address("street", "city", "state", "country", "zipcode"); | |||||
} | } | ||||
} | |||||
public class OrderBuilder | |||||
{ | |||||
private readonly Order order; | |||||
public class OrderBuilder | |||||
{ | |||||
private readonly Order order; | |||||
public OrderBuilder(Address address) | |||||
{ | |||||
order = new Order( | |||||
"userId", | |||||
"fakeName", | |||||
address, | |||||
cardTypeId: 5, | |||||
cardNumber: "12", | |||||
cardSecurityNumber: "123", | |||||
cardHolderName: "name", | |||||
cardExpiration: DateTime.UtcNow); | |||||
} | |||||
public OrderBuilder(Address address) | |||||
{ | |||||
order = new Order( | |||||
"userId", | |||||
"fakeName", | |||||
address, | |||||
cardTypeId: 5, | |||||
cardNumber: "12", | |||||
cardSecurityNumber: "123", | |||||
cardHolderName: "name", | |||||
cardExpiration: DateTime.UtcNow); | |||||
} | |||||
public OrderBuilder AddOne( | |||||
int productId, | |||||
string productName, | |||||
decimal unitPrice, | |||||
decimal discount, | |||||
string pictureUrl, | |||||
int units = 1) | |||||
{ | |||||
order.AddOrderItem(productId, productName, unitPrice, discount, pictureUrl, units); | |||||
return this; | |||||
} | |||||
public OrderBuilder AddOne( | |||||
int productId, | |||||
string productName, | |||||
decimal unitPrice, | |||||
decimal discount, | |||||
string pictureUrl, | |||||
int units = 1) | |||||
{ | |||||
order.AddOrderItem(productId, productName, unitPrice, discount, pictureUrl, units); | |||||
return this; | |||||
} | |||||
public Order Build() | |||||
{ | |||||
return order; | |||||
} | |||||
public Order Build() | |||||
{ | |||||
return order; | |||||
} | } | ||||
} | } |
@ -1,189 +1,182 @@ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using Xunit; | |||||
namespace Ordering.UnitTests.Domain.SeedWork; | |||||
namespace Ordering.UnitTests.Domain.SeedWork | |||||
public class ValueObjectTests | |||||
{ | { | ||||
public class ValueObjectTests | |||||
{ | |||||
public ValueObjectTests() | |||||
{ } | |||||
public ValueObjectTests() | |||||
{ } | |||||
[Theory] | |||||
[MemberData(nameof(EqualValueObjects))] | |||||
public void Equals_EqualValueObjects_ReturnsTrue(ValueObject instanceA, ValueObject instanceB, string reason) | |||||
{ | |||||
// Act | |||||
var result = EqualityComparer<ValueObject>.Default.Equals(instanceA, instanceB); | |||||
[Theory] | |||||
[MemberData(nameof(EqualValueObjects))] | |||||
public void Equals_EqualValueObjects_ReturnsTrue(ValueObject instanceA, ValueObject instanceB, string reason) | |||||
{ | |||||
// Act | |||||
var result = EqualityComparer<ValueObject>.Default.Equals(instanceA, instanceB); | |||||
// Assert | |||||
Assert.True(result, reason); | |||||
} | |||||
// Assert | |||||
Assert.True(result, reason); | |||||
} | |||||
[Theory] | |||||
[MemberData(nameof(NonEqualValueObjects))] | |||||
public void Equals_NonEqualValueObjects_ReturnsFalse(ValueObject instanceA, ValueObject instanceB, string reason) | |||||
{ | |||||
// Act | |||||
var result = EqualityComparer<ValueObject>.Default.Equals(instanceA, instanceB); | |||||
[Theory] | |||||
[MemberData(nameof(NonEqualValueObjects))] | |||||
public void Equals_NonEqualValueObjects_ReturnsFalse(ValueObject instanceA, ValueObject instanceB, string reason) | |||||
{ | |||||
// Act | |||||
var result = EqualityComparer<ValueObject>.Default.Equals(instanceA, instanceB); | |||||
// Assert | |||||
Assert.False(result, reason); | |||||
} | |||||
// Assert | |||||
Assert.False(result, reason); | |||||
} | |||||
private static readonly ValueObject APrettyValueObject = new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")); | |||||
private static readonly ValueObject APrettyValueObject = new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")); | |||||
public static readonly TheoryData<ValueObject, ValueObject, string> EqualValueObjects = new TheoryData<ValueObject, ValueObject, string> | |||||
public static readonly TheoryData<ValueObject, ValueObject, string> EqualValueObjects = new TheoryData<ValueObject, ValueObject, string> | |||||
{ | |||||
{ | { | ||||
{ | |||||
null, | |||||
null, | |||||
"they should be equal because they are both null" | |||||
}, | |||||
{ | |||||
APrettyValueObject, | |||||
APrettyValueObject, | |||||
"they should be equal because they are the same object" | |||||
}, | |||||
{ | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), | |||||
"they should be equal because they have equal members" | |||||
}, | |||||
{ | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto"), | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto2"), | |||||
"they should be equal because all equality components are equal, even though an additional member was set" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
"they should be equal because all equality components are equal, including the 'C' list" | |||||
} | |||||
}; | |||||
null, | |||||
null, | |||||
"they should be equal because they are both null" | |||||
}, | |||||
{ | |||||
APrettyValueObject, | |||||
APrettyValueObject, | |||||
"they should be equal because they are the same object" | |||||
}, | |||||
{ | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), | |||||
"they should be equal because they have equal members" | |||||
}, | |||||
{ | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto"), | |||||
new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto2"), | |||||
"they should be equal because all equality components are equal, even though an additional member was set" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
"they should be equal because all equality components are equal, including the 'C' list" | |||||
} | |||||
}; | |||||
public static readonly TheoryData<ValueObject, ValueObject, string> NonEqualValueObjects = new TheoryData<ValueObject, ValueObject, string> | |||||
public static readonly TheoryData<ValueObject, ValueObject, string> NonEqualValueObjects = new TheoryData<ValueObject, ValueObject, string> | |||||
{ | |||||
{ | { | ||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
new ValueObjectA(a: 2, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
"they should not be equal because the 'A' member on ValueObjectA is different among them" | |||||
}, | |||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
new ValueObjectA(a: 1, b: null, c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
"they should not be equal because the 'B' member on ValueObjectA is different among them" | |||||
}, | |||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 3, b: "3")), | |||||
"they should not be equal because the 'A' member on ValueObjectA's 'D' member is different among them" | |||||
}, | |||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), | |||||
new ValueObjectB(a: 1, b: "2"), | |||||
"they should not be equal because they are not of the same type" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3, 4 ), | |||||
"they should be not be equal because the 'C' list contains one additional value" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3, 5 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
"they should be not be equal because the 'C' list contains one additional value" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3, 5 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3, 4 ), | |||||
"they should be not be equal because the 'C' lists are not equal" | |||||
} | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
new ValueObjectA(a: 2, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
"they should not be equal because the 'A' member on ValueObjectA is different among them" | |||||
}, | |||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
new ValueObjectA(a: 1, b: null, c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), | |||||
"they should not be equal because the 'B' member on ValueObjectA is different among them" | |||||
}, | |||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 3, b: "3")), | |||||
"they should not be equal because the 'A' member on ValueObjectA's 'D' member is different among them" | |||||
}, | |||||
{ | |||||
new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), | |||||
new ValueObjectB(a: 1, b: "2"), | |||||
"they should not be equal because they are not of the same type" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3, 4 ), | |||||
"they should be not be equal because the 'C' list contains one additional value" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3, 5 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3 ), | |||||
"they should be not be equal because the 'C' list contains one additional value" | |||||
}, | |||||
{ | |||||
new ValueObjectB(1, "2", 1, 2, 3, 5 ), | |||||
new ValueObjectB(1, "2", 1, 2, 3, 4 ), | |||||
"they should be not be equal because the 'C' lists are not equal" | |||||
} | |||||
}; | |||||
}; | |||||
private class ValueObjectA : ValueObject | |||||
private class ValueObjectA : ValueObject | |||||
{ | |||||
public ValueObjectA(int a, string b, Guid c, ComplexObject d, string notAnEqualityComponent = null) | |||||
{ | { | ||||
public ValueObjectA(int a, string b, Guid c, ComplexObject d, string notAnEqualityComponent = null) | |||||
{ | |||||
A = a; | |||||
B = b; | |||||
C = c; | |||||
D = d; | |||||
NotAnEqualityComponent = notAnEqualityComponent; | |||||
} | |||||
A = a; | |||||
B = b; | |||||
C = c; | |||||
D = d; | |||||
NotAnEqualityComponent = notAnEqualityComponent; | |||||
} | |||||
public int A { get; } | |||||
public string B { get; } | |||||
public Guid C { get; } | |||||
public ComplexObject D { get; } | |||||
public string NotAnEqualityComponent { get; } | |||||
public int A { get; } | |||||
public string B { get; } | |||||
public Guid C { get; } | |||||
public ComplexObject D { get; } | |||||
public string NotAnEqualityComponent { get; } | |||||
protected override IEnumerable<object> GetEqualityComponents() | |||||
{ | |||||
yield return A; | |||||
yield return B; | |||||
yield return C; | |||||
yield return D; | |||||
} | |||||
protected override IEnumerable<object> GetEqualityComponents() | |||||
{ | |||||
yield return A; | |||||
yield return B; | |||||
yield return C; | |||||
yield return D; | |||||
} | } | ||||
} | |||||
private class ValueObjectB : ValueObject | |||||
private class ValueObjectB : ValueObject | |||||
{ | |||||
public ValueObjectB(int a, string b, params int[] c) | |||||
{ | { | ||||
public ValueObjectB(int a, string b, params int[] c) | |||||
{ | |||||
A = a; | |||||
B = b; | |||||
C = c.ToList(); | |||||
} | |||||
A = a; | |||||
B = b; | |||||
C = c.ToList(); | |||||
} | |||||
public int A { get; } | |||||
public string B { get; } | |||||
public int A { get; } | |||||
public string B { get; } | |||||
public List<int> C { get; } | |||||
public List<int> C { get; } | |||||
protected override IEnumerable<object> GetEqualityComponents() | |||||
{ | |||||
yield return A; | |||||
yield return B; | |||||
protected override IEnumerable<object> GetEqualityComponents() | |||||
{ | |||||
yield return A; | |||||
yield return B; | |||||
foreach (var c in C) | |||||
{ | |||||
yield return c; | |||||
} | |||||
foreach (var c in C) | |||||
{ | |||||
yield return c; | |||||
} | } | ||||
} | } | ||||
} | |||||
private class ComplexObject : IEquatable<ComplexObject> | |||||
private class ComplexObject : IEquatable<ComplexObject> | |||||
{ | |||||
public ComplexObject(int a, string b) | |||||
{ | { | ||||
public ComplexObject(int a, string b) | |||||
{ | |||||
A = a; | |||||
B = b; | |||||
} | |||||
A = a; | |||||
B = b; | |||||
} | |||||
public int A { get; set; } | |||||
public int A { get; set; } | |||||
public string B { get; set; } | |||||
public string B { get; set; } | |||||
public override bool Equals(object obj) | |||||
{ | |||||
return Equals(obj as ComplexObject); | |||||
} | |||||
public override bool Equals(object obj) | |||||
{ | |||||
return Equals(obj as ComplexObject); | |||||
} | |||||
public bool Equals(ComplexObject other) | |||||
{ | |||||
return other != null && | |||||
A == other.A && | |||||
B == other.B; | |||||
} | |||||
public bool Equals(ComplexObject other) | |||||
{ | |||||
return other != null && | |||||
A == other.A && | |||||
B == other.B; | |||||
} | |||||
public override int GetHashCode() | |||||
{ | |||||
return HashCode.Combine(A, B); | |||||
} | |||||
public override int GetHashCode() | |||||
{ | |||||
return HashCode.Combine(A, B); | |||||
} | } | ||||
} | } | ||||
} | } |