From 3e228035c071ec6e0406f73a7ef6dc0dc303c84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Michel?= Date: Mon, 3 Feb 2020 20:47:59 +0100 Subject: [PATCH] Feature/respect encapsulation (#349) * resolve osbsolete method * put all properties as private, align unit test * fix version of version in MD, add instruction to install ef tool * fix url stored --- README.md | 6 ++- src/ApplicationCore/Entities/BaseEntity.cs | 4 +- .../Entities/BasketAggregate/Basket.cs | 21 ++++++---- .../Entities/BasketAggregate/BasketItem.cs | 24 +++++++++-- .../Entities/BuyerAggregate/PaymentMethod.cs | 6 +-- src/ApplicationCore/Entities/CatalogBrand.cs | 6 ++- src/ApplicationCore/Entities/CatalogItem.cs | 36 ++++++++++++---- src/ApplicationCore/Entities/CatalogType.cs | 6 ++- .../Entities/OrderAggregate/Address.cs | 10 ++--- src/ApplicationCore/Services/BasketService.cs | 6 +-- src/ApplicationCore/Services/OrderService.cs | 7 +++- src/Infrastructure/Data/CatalogContextSeed.cs | 42 +++++++++---------- .../Data/Config/CatalogTypeConfiguration.cs | 2 +- src/Web/Pages/Admin/EditCatalogItem.cshtml.cs | 2 +- src/Web/Services/BasketViewModelService.cs | 2 +- .../Services/CatalogItemViewModelService.cs | 10 +---- src/Web/Services/CatalogViewModelService.cs | 9 +--- .../Entities/BasketTests/BasketAddItem.cs | 17 ++++---- .../BasketServiceTests/DeleteBasket.cs | 5 ++- .../BasketWithItemsSpecification.cs | 17 ++++++-- .../CatalogFilterSpecificationFilter.cs | 11 ++--- tests/UnitTests/Builders/BasketBuilder.cs | 12 ++++-- 22 files changed, 162 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index 08cdd0777..4c7186a21 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The **eShopOnWeb** sample is related to the [eShopOnContainers](https://github.c The goal for this sample is to demonstrate some of the principles and patterns described in the [eBook](https://aka.ms/webappebook). It is not meant to be an eCommerce reference application, and as such it does not implement many features that would be obvious and/or essential to a real eCommerce application. > ### VERSIONS -> #### The `master` branch is currently running ASP.NET Core 2.2. +> #### The `master` branch is currently running ASP.NET Core 3.1. > #### Older versions are tagged. ## Topics (eBook TOC) @@ -58,6 +58,10 @@ You can also run the samples in Docker (see below). ``` 1. Ensure your connection strings in `appsettings.json` point to a local SQL Server instance. +1. Ensure the tool EF was already installed. You can find some help [here](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet) +``` +dotnet tool install --global dotnet-ef +``` 1. Open a command prompt in the Web folder and execute the following commands: diff --git a/src/ApplicationCore/Entities/BaseEntity.cs b/src/ApplicationCore/Entities/BaseEntity.cs index 78dc78f49..596e7c16b 100644 --- a/src/ApplicationCore/Entities/BaseEntity.cs +++ b/src/ApplicationCore/Entities/BaseEntity.cs @@ -2,8 +2,8 @@ { // This can easily be modified to be BaseEntity and public T Id to support different key types. // Using non-generic integer types for simplicity and to ease caching logic - public class BaseEntity + public abstract class BaseEntity { - public int Id { get; set; } + public virtual int Id { get; protected set; } } } diff --git a/src/ApplicationCore/Entities/BasketAggregate/Basket.cs b/src/ApplicationCore/Entities/BasketAggregate/Basket.cs index 7b89bd543..94c803e72 100644 --- a/src/ApplicationCore/Entities/BasketAggregate/Basket.cs +++ b/src/ApplicationCore/Entities/BasketAggregate/Basket.cs @@ -6,29 +6,34 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate { public class Basket : BaseEntity, IAggregateRoot { - public string BuyerId { get; set; } + public string BuyerId { get; private set; } private readonly List _items = new List(); public IReadOnlyCollection Items => _items.AsReadOnly(); + public Basket(string buyerId) + { + BuyerId = buyerId; + } + public void AddItem(int catalogItemId, decimal unitPrice, int quantity = 1) { if (!Items.Any(i => i.CatalogItemId == catalogItemId)) { - _items.Add(new BasketItem() - { - CatalogItemId = catalogItemId, - Quantity = quantity, - UnitPrice = unitPrice - }); + _items.Add(new BasketItem(catalogItemId, quantity, unitPrice)); return; } var existingItem = Items.FirstOrDefault(i => i.CatalogItemId == catalogItemId); - existingItem.Quantity += quantity; + existingItem.AddQuantity(quantity); } public void RemoveEmptyItems() { _items.RemoveAll(i => i.Quantity == 0); } + + public void SetNewBuyerId(string buyerId) + { + BuyerId = buyerId; + } } } diff --git a/src/ApplicationCore/Entities/BasketAggregate/BasketItem.cs b/src/ApplicationCore/Entities/BasketAggregate/BasketItem.cs index d065e4b48..6b6dc39a7 100644 --- a/src/ApplicationCore/Entities/BasketAggregate/BasketItem.cs +++ b/src/ApplicationCore/Entities/BasketAggregate/BasketItem.cs @@ -2,9 +2,27 @@ { public class BasketItem : BaseEntity { - public decimal UnitPrice { get; set; } - public int Quantity { get; set; } - public int CatalogItemId { get; set; } + + public decimal UnitPrice { get; private set; } + public int Quantity { get; private set; } + public int CatalogItemId { get; private set; } public int BasketId { get; private set; } + + public BasketItem(int catalogItemId, int quantity, decimal unitPrice) + { + CatalogItemId = catalogItemId; + Quantity = quantity; + UnitPrice = unitPrice; + } + + public void AddQuantity(int quantity) + { + Quantity += quantity; + } + + public void SetNewQuantity(int quantity) + { + Quantity = quantity; + } } } diff --git a/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs b/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs index 631ed4e78..9bd193856 100644 --- a/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs +++ b/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs @@ -2,8 +2,8 @@ { public class PaymentMethod : BaseEntity { - public string Alias { get; set; } - public string CardId { get; set; } // actual card data must be stored in a PCI compliant system, like Stripe - public string Last4 { get; set; } + public string Alias { get; private set; } + public string CardId { get; private set; } // actual card data must be stored in a PCI compliant system, like Stripe + public string Last4 { get; private set; } } } diff --git a/src/ApplicationCore/Entities/CatalogBrand.cs b/src/ApplicationCore/Entities/CatalogBrand.cs index 873a74a31..44dc7d0a4 100644 --- a/src/ApplicationCore/Entities/CatalogBrand.cs +++ b/src/ApplicationCore/Entities/CatalogBrand.cs @@ -4,6 +4,10 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities { public class CatalogBrand : BaseEntity, IAggregateRoot { - public string Brand { get; set; } + public string Brand { get; private set; } + public CatalogBrand(string brand) + { + Brand = brand; + } } } diff --git a/src/ApplicationCore/Entities/CatalogItem.cs b/src/ApplicationCore/Entities/CatalogItem.cs index 815be2681..caa856205 100644 --- a/src/ApplicationCore/Entities/CatalogItem.cs +++ b/src/ApplicationCore/Entities/CatalogItem.cs @@ -1,16 +1,34 @@ -using Microsoft.eShopWeb.ApplicationCore.Interfaces; +using Ardalis.GuardClauses; +using Microsoft.eShopWeb.ApplicationCore.Interfaces; namespace Microsoft.eShopWeb.ApplicationCore.Entities { public class CatalogItem : BaseEntity, IAggregateRoot { - public string Name { get; set; } - public string Description { get; set; } - public decimal Price { get; set; } - public string PictureUri { get; set; } - public int CatalogTypeId { get; set; } - public CatalogType CatalogType { get; set; } - public int CatalogBrandId { get; set; } - public CatalogBrand CatalogBrand { get; set; } + public string Name { get; private set; } + public string Description { get; private set; } + public decimal Price { get; private set; } + public string PictureUri { get; private set; } + public int CatalogTypeId { get; private set; } + public CatalogType CatalogType { get; private set; } + public int CatalogBrandId { get; private set; } + public CatalogBrand CatalogBrand { get; private set; } + + public CatalogItem(int catalogTypeId, int catalogBrandId, string description, string name, decimal price, string pictureUri) + { + CatalogTypeId = catalogTypeId; + CatalogBrandId = catalogBrandId; + Description = description; + Name = name; + Price = price; + PictureUri = pictureUri; + } + + public void Update(string name, decimal price) + { + Guard.Against.NullOrEmpty(name, nameof(name)); + Name = name; + Price = price; + } } } \ No newline at end of file diff --git a/src/ApplicationCore/Entities/CatalogType.cs b/src/ApplicationCore/Entities/CatalogType.cs index 869ce8c45..f0e7f8c79 100644 --- a/src/ApplicationCore/Entities/CatalogType.cs +++ b/src/ApplicationCore/Entities/CatalogType.cs @@ -4,6 +4,10 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities { public class CatalogType : BaseEntity, IAggregateRoot { - public string Type { get; set; } + public string Type { get; private set; } + public CatalogType(string type) + { + Type = type; + } } } diff --git a/src/ApplicationCore/Entities/OrderAggregate/Address.cs b/src/ApplicationCore/Entities/OrderAggregate/Address.cs index 1c9fd64b2..3e99159fd 100644 --- a/src/ApplicationCore/Entities/OrderAggregate/Address.cs +++ b/src/ApplicationCore/Entities/OrderAggregate/Address.cs @@ -4,15 +4,15 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate { public class Address // ValueObject { - public String Street { get; private set; } + public string Street { get; private set; } - public String City { get; private set; } + public string City { get; private set; } - public String State { get; private set; } + public string State { get; private set; } - public String Country { get; private set; } + public string Country { get; private set; } - public String ZipCode { get; private set; } + public string ZipCode { get; private set; } private Address() { } diff --git a/src/ApplicationCore/Services/BasketService.cs b/src/ApplicationCore/Services/BasketService.cs index 6b210d5c8..f3f0dd86a 100644 --- a/src/ApplicationCore/Services/BasketService.cs +++ b/src/ApplicationCore/Services/BasketService.cs @@ -59,8 +59,8 @@ public async Task SetQuantities(int basketId, Dictionary quantities { if (quantities.TryGetValue(item.Id.ToString(), out var quantity)) { - if(_logger != null) _logger.LogInformation($"Updating quantity of item ID:{item.Id} to {quantity}."); - item.Quantity = quantity; + if (_logger != null) _logger.LogInformation($"Updating quantity of item ID:{item.Id} to {quantity}."); + item.SetNewQuantity(quantity); } } basket.RemoveEmptyItems(); @@ -74,7 +74,7 @@ public async Task TransferBasketAsync(string anonymousId, string userName) var basketSpec = new BasketWithItemsSpecification(anonymousId); var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault(); if (basket == null) return; - basket.BuyerId = userName; + basket.SetNewBuyerId(userName); await _basketRepository.UpdateAsync(basket); } } diff --git a/src/ApplicationCore/Services/OrderService.cs b/src/ApplicationCore/Services/OrderService.cs index 01cd3a4ae..632e7ea39 100644 --- a/src/ApplicationCore/Services/OrderService.cs +++ b/src/ApplicationCore/Services/OrderService.cs @@ -11,14 +11,17 @@ namespace Microsoft.eShopWeb.ApplicationCore.Services public class OrderService : IOrderService { private readonly IAsyncRepository _orderRepository; + private readonly IUriComposer _uriComposer; private readonly IAsyncRepository _basketRepository; private readonly IAsyncRepository _itemRepository; public OrderService(IAsyncRepository basketRepository, IAsyncRepository itemRepository, - IAsyncRepository orderRepository) + IAsyncRepository orderRepository, + IUriComposer uriComposer) { _orderRepository = orderRepository; + _uriComposer = uriComposer; _basketRepository = basketRepository; _itemRepository = itemRepository; } @@ -31,7 +34,7 @@ public async Task CreateOrderAsync(int basketId, Address shippingAddress) foreach (var item in basket.Items) { var catalogItem = await _itemRepository.GetByIdAsync(item.CatalogItemId); - var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, catalogItem.PictureUri); + var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name,_uriComposer.ComposePicUri(catalogItem.PictureUri)); var orderItem = new OrderItem(itemOrdered, item.UnitPrice, item.Quantity); items.Add(orderItem); } diff --git a/src/Infrastructure/Data/CatalogContextSeed.cs b/src/Infrastructure/Data/CatalogContextSeed.cs index 1cfa04322..9ea74b2ef 100644 --- a/src/Infrastructure/Data/CatalogContextSeed.cs +++ b/src/Infrastructure/Data/CatalogContextSeed.cs @@ -59,11 +59,11 @@ static IEnumerable GetPreconfiguredCatalogBrands() { return new List() { - new CatalogBrand() { Brand = "Azure"}, - new CatalogBrand() { Brand = ".NET" }, - new CatalogBrand() { Brand = "Visual Studio" }, - new CatalogBrand() { Brand = "SQL Server" }, - new CatalogBrand() { Brand = "Other" } + new CatalogBrand("Azure"), + new CatalogBrand(".NET"), + new CatalogBrand("Visual Studio"), + new CatalogBrand("SQL Server"), + new CatalogBrand("Other") }; } @@ -71,10 +71,10 @@ static IEnumerable GetPreconfiguredCatalogTypes() { return new List() { - new CatalogType() { Type = "Mug"}, - new CatalogType() { Type = "T-Shirt" }, - new CatalogType() { Type = "Sheet" }, - new CatalogType() { Type = "USB Memory Stick" } + new CatalogType("Mug"), + new CatalogType("T-Shirt"), + new CatalogType("Sheet"), + new CatalogType("USB Memory Stick") }; } @@ -82,18 +82,18 @@ static IEnumerable GetPreconfiguredItems() { return new List() { - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Bot Black Sweatshirt", Name = ".NET Bot Black Sweatshirt", Price = 19.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/1.png" }, - new CatalogItem() { CatalogTypeId=1,CatalogBrandId=2, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureUri = "http://catalogbaseurltobereplaced/images/products/2.png" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/3.png" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Foundation Sweatshirt", Name = ".NET Foundation Sweatshirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/4.png" }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=5, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/5.png" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=2, Description = ".NET Blue Sweatshirt", Name = ".NET Blue Sweatshirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/6.png" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/7.png" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Kudu Purple Sweatshirt", Name = "Kudu Purple Sweatshirt", Price = 8.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/8.png" }, - new CatalogItem() { CatalogTypeId=1,CatalogBrandId=5, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/9.png" }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/10.png" }, - new CatalogItem() { CatalogTypeId=3,CatalogBrandId=2, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureUri = "http://catalogbaseurltobereplaced/images/products/11.png" }, - new CatalogItem() { CatalogTypeId=2,CatalogBrandId=5, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureUri = "http://catalogbaseurltobereplaced/images/products/12.png" } + new CatalogItem(2,2, ".NET Bot Black Sweatshirt", ".NET Bot Black Sweatshirt", 19.5M, "http://catalogbaseurltobereplaced/images/products/1.png"), + new CatalogItem(1,2, ".NET Black & White Mug", ".NET Black & White Mug", 8.50M, "http://catalogbaseurltobereplaced/images/products/2.png"), + new CatalogItem(2,5, "Prism White T-Shirt", "Prism White T-Shirt", 12, "http://catalogbaseurltobereplaced/images/products/3.png"), + new CatalogItem(2,2, ".NET Foundation Sweatshirt", ".NET Foundation Sweatshirt", 12, "http://catalogbaseurltobereplaced/images/products/4.png"), + new CatalogItem(3,5, "Roslyn Red Sheet", "Roslyn Red Sheet", 8.5M, "http://catalogbaseurltobereplaced/images/products/5.png"), + new CatalogItem(2,2, ".NET Blue Sweatshirt", ".NET Blue Sweatshirt", 12, "http://catalogbaseurltobereplaced/images/products/6.png"), + new CatalogItem(2,5, "Roslyn Red T-Shirt", "Roslyn Red T-Shirt", 12, "http://catalogbaseurltobereplaced/images/products/7.png"), + new CatalogItem(2,5, "Kudu Purple Sweatshirt", "Kudu Purple Sweatshirt", 8.5M, "http://catalogbaseurltobereplaced/images/products/8.png"), + new CatalogItem(1,5, "Cup White Mug", "Cup White Mug", 12, "http://catalogbaseurltobereplaced/images/products/9.png"), + new CatalogItem(3,2, ".NET Foundation Sheet", ".NET Foundation Sheet", 12, "http://catalogbaseurltobereplaced/images/products/10.png"), + new CatalogItem(3,2, "Cup Sheet", "Cup Sheet", 8.5M, "http://catalogbaseurltobereplaced/images/products/11.png"), + new CatalogItem(2,5, "Prism White TShirt", "Prism White TShirt", 12, "http://catalogbaseurltobereplaced/images/products/12.png") }; } } diff --git a/src/Infrastructure/Data/Config/CatalogTypeConfiguration.cs b/src/Infrastructure/Data/Config/CatalogTypeConfiguration.cs index 1f465bd58..5caa01c7c 100644 --- a/src/Infrastructure/Data/Config/CatalogTypeConfiguration.cs +++ b/src/Infrastructure/Data/Config/CatalogTypeConfiguration.cs @@ -11,7 +11,7 @@ public void Configure(EntityTypeBuilder builder) builder.HasKey(ci => ci.Id); builder.Property(ci => ci.Id) - .ForSqlServerUseSequenceHiLo("catalog_type_hilo") + .UseHiLo("catalog_type_hilo") .IsRequired(); builder.Property(cb => cb.Type) diff --git a/src/Web/Pages/Admin/EditCatalogItem.cshtml.cs b/src/Web/Pages/Admin/EditCatalogItem.cshtml.cs index 0dd4af29e..6e1a7fe8d 100644 --- a/src/Web/Pages/Admin/EditCatalogItem.cshtml.cs +++ b/src/Web/Pages/Admin/EditCatalogItem.cshtml.cs @@ -21,7 +21,7 @@ public EditCatalogItemModel(ICatalogItemViewModelService catalogItemViewModelSer [BindProperty] public CatalogItemViewModel CatalogModel { get; set; } = new CatalogItemViewModel(); - public async Task OnGet(CatalogItemViewModel catalogModel) + public void OnGet(CatalogItemViewModel catalogModel) { CatalogModel = catalogModel; } diff --git a/src/Web/Services/BasketViewModelService.cs b/src/Web/Services/BasketViewModelService.cs index b4801f66c..d0db78f5e 100644 --- a/src/Web/Services/BasketViewModelService.cs +++ b/src/Web/Services/BasketViewModelService.cs @@ -48,7 +48,7 @@ private async Task CreateViewModelFromBasket(Basket basket) private async Task CreateBasketForUser(string userId) { - var basket = new Basket() { BuyerId = userId }; + var basket = new Basket(userId); await _basketRepository.AddAsync(basket); return new BasketViewModel() diff --git a/src/Web/Services/CatalogItemViewModelService.cs b/src/Web/Services/CatalogItemViewModelService.cs index 551b2cde5..8d9358503 100644 --- a/src/Web/Services/CatalogItemViewModelService.cs +++ b/src/Web/Services/CatalogItemViewModelService.cs @@ -17,15 +17,9 @@ public CatalogItemViewModelService(IAsyncRepository catalogItemRepo public async Task UpdateCatalogItem(CatalogItemViewModel viewModel) { - //Get existing CatalogItem var existingCatalogItem = await _catalogItemRepository.GetByIdAsync(viewModel.Id); - - //Build updated CatalogItem - var updatedCatalogItem = existingCatalogItem; - updatedCatalogItem.Name = viewModel.Name; - updatedCatalogItem.Price = viewModel.Price; - - await _catalogItemRepository.UpdateAsync(updatedCatalogItem); + existingCatalogItem.Update(viewModel.Name, viewModel.Price); + await _catalogItemRepository.UpdateAsync(existingCatalogItem); } } } diff --git a/src/Web/Services/CatalogViewModelService.cs b/src/Web/Services/CatalogViewModelService.cs index 20e8bef9c..1c615a03d 100644 --- a/src/Web/Services/CatalogViewModelService.cs +++ b/src/Web/Services/CatalogViewModelService.cs @@ -48,19 +48,14 @@ public async Task GetCatalogItems(int pageIndex, int item // the implementation below using ForEach and Count. We need a List. var itemsOnPage = await _itemRepository.ListAsync(filterPaginatedSpecification); var totalItems = await _itemRepository.CountAsync(filterSpecification); - - foreach (var itemOnPage in itemsOnPage) - { - itemOnPage.PictureUri = _uriComposer.ComposePicUri(itemOnPage.PictureUri); - } - + var vm = new CatalogIndexViewModel() { CatalogItems = itemsOnPage.Select(i => new CatalogItemViewModel() { Id = i.Id, Name = i.Name, - PictureUri = i.PictureUri, + PictureUri = _uriComposer.ComposePicUri(i.PictureUri), Price = i.Price }), Brands = await GetBrands(), diff --git a/tests/UnitTests/ApplicationCore/Entities/BasketTests/BasketAddItem.cs b/tests/UnitTests/ApplicationCore/Entities/BasketTests/BasketAddItem.cs index 173461c93..7f788a459 100644 --- a/tests/UnitTests/ApplicationCore/Entities/BasketTests/BasketAddItem.cs +++ b/tests/UnitTests/ApplicationCore/Entities/BasketTests/BasketAddItem.cs @@ -6,14 +6,15 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.BasketTests { public class BasketAddItem { - private int _testCatalogItemId = 123; - private decimal _testUnitPrice = 1.23m; - private int _testQuantity = 2; + private readonly int _testCatalogItemId = 123; + private readonly decimal _testUnitPrice = 1.23m; + private readonly int _testQuantity = 2; + private readonly string _buyerId = "Test buyerId"; [Fact] public void AddsBasketItemIfNotPresent() { - var basket = new Basket(); + var basket = new Basket(_buyerId); basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity); var firstItem = basket.Items.Single(); @@ -25,7 +26,7 @@ public void AddsBasketItemIfNotPresent() [Fact] public void IncrementsQuantityOfItemIfPresent() { - var basket = new Basket(); + var basket = new Basket(_buyerId); basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity); basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity); @@ -36,7 +37,7 @@ public void IncrementsQuantityOfItemIfPresent() [Fact] public void KeepsOriginalUnitPriceIfMoreItemsAdded() { - var basket = new Basket(); + var basket = new Basket(_buyerId); basket.AddItem(_testCatalogItemId, _testUnitPrice, _testQuantity); basket.AddItem(_testCatalogItemId, _testUnitPrice * 2, _testQuantity); @@ -47,7 +48,7 @@ public void KeepsOriginalUnitPriceIfMoreItemsAdded() [Fact] public void DefaultsToQuantityOfOne() { - var basket = new Basket(); + var basket = new Basket(_buyerId); basket.AddItem(_testCatalogItemId, _testUnitPrice); var firstItem = basket.Items.Single(); @@ -57,7 +58,7 @@ public void DefaultsToQuantityOfOne() [Fact] public void RemoveEmptyItems() { - var basket = new Basket(); + var basket = new Basket(_buyerId); basket.AddItem(_testCatalogItemId, _testUnitPrice, 0); basket.RemoveEmptyItems(); diff --git a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs index b7a63d799..05a56c098 100644 --- a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs +++ b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs @@ -9,7 +9,8 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes { public class DeleteBasket { - private Mock> _mockBasketRepo; + private readonly string _buyerId = "Test buyerId"; + private readonly Mock> _mockBasketRepo; public DeleteBasket() { @@ -19,7 +20,7 @@ public DeleteBasket() [Fact] public async Task Should_InvokeBasketRepositoryDeleteAsync_Once() { - var basket = new Basket(); + var basket = new Basket(_buyerId); basket.AddItem(1, It.IsAny(), It.IsAny()); basket.AddItem(2, It.IsAny(), It.IsAny()); _mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny())) diff --git a/tests/UnitTests/ApplicationCore/Specifications/BasketWithItemsSpecification.cs b/tests/UnitTests/ApplicationCore/Specifications/BasketWithItemsSpecification.cs index ee55a9df7..a29666b2e 100644 --- a/tests/UnitTests/ApplicationCore/Specifications/BasketWithItemsSpecification.cs +++ b/tests/UnitTests/ApplicationCore/Specifications/BasketWithItemsSpecification.cs @@ -3,12 +3,14 @@ using System.Collections.Generic; using System.Linq; using Xunit; +using Moq; namespace Microsoft.eShopWeb.UnitTests { public class BasketWithItems { - private int _testBasketId = 123; + private readonly int _testBasketId = 123; + private readonly string _buyerId = "Test buyerId"; [Fact] public void MatchesBasketWithGivenId() @@ -37,11 +39,18 @@ public void MatchesNoBasketsIfIdNotPresent() public List GetTestBasketCollection() { + var basket1Mock = new Mock(_buyerId); + basket1Mock.SetupGet(s => s.Id).Returns(1); + var basket2Mock = new Mock(_buyerId); + basket2Mock.SetupGet(s => s.Id).Returns(2); + var basket3Mock = new Mock(_buyerId); + basket3Mock.SetupGet(s => s.Id).Returns(_testBasketId); + return new List() { - new Basket() { Id = 1 }, - new Basket() { Id = 2 }, - new Basket() { Id = _testBasketId } + basket1Mock.Object, + basket2Mock.Object, + basket3Mock.Object }; } } diff --git a/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecificationFilter.cs b/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecificationFilter.cs index fa215bf2a..2d760d8e8 100644 --- a/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecificationFilter.cs +++ b/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecificationFilter.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Xunit; +using Moq; namespace Microsoft.eShopWeb.UnitTests { @@ -31,11 +32,11 @@ public List GetTestItemCollection() { return new List() { - new CatalogItem() { Id = 1, CatalogBrandId = 1, CatalogTypeId= 1 }, - new CatalogItem() { Id = 2, CatalogBrandId = 1, CatalogTypeId= 2 }, - new CatalogItem() { Id = 3, CatalogBrandId = 1, CatalogTypeId= 3 }, - new CatalogItem() { Id = 4, CatalogBrandId = 2, CatalogTypeId= 1 }, - new CatalogItem() { Id = 5, CatalogBrandId = 2, CatalogTypeId= 2 }, + new CatalogItem(1, 1, "Description", "Name", 0, "FakePath"), + new CatalogItem(2, 1, "Description", "Name", 0, "FakePath"), + new CatalogItem(3, 1, "Description", "Name", 0, "FakePath"), + new CatalogItem(1, 2, "Description", "Name", 0, "FakePath"), + new CatalogItem(2, 2, "Description", "Name", 0, "FakePath"), }; } } diff --git a/tests/UnitTests/Builders/BasketBuilder.cs b/tests/UnitTests/Builders/BasketBuilder.cs index 10d063292..40860e9bd 100644 --- a/tests/UnitTests/Builders/BasketBuilder.cs +++ b/tests/UnitTests/Builders/BasketBuilder.cs @@ -1,11 +1,13 @@ using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate; +using Moq; namespace Microsoft.eShopWeb.UnitTests.Builders { public class BasketBuilder { - private Basket _basket; + private Basket _basket; public string BasketBuyerId => "testbuyerId@test.com"; + public int BasketId => 1; public BasketBuilder() @@ -20,13 +22,17 @@ public Basket Build() public Basket WithNoItems() { - _basket = new Basket { BuyerId = BasketBuyerId, Id = BasketId }; + var basketMock = new Mock(BasketBuyerId); + basketMock.SetupGet(s => s.Id).Returns(BasketId); + + _basket = basketMock.Object; return _basket; } public Basket WithOneBasketItem() { - _basket = new Basket { BuyerId = BasketBuyerId, Id = BasketId }; + var basketMock = new Mock(BasketBuyerId); + _basket = basketMock.Object; _basket.AddItem(2, 3.40m, 4); return _basket; }