From 814d3e249c8eef1ffa344c9182f5844560ce562b Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Thu, 31 May 2018 12:28:55 -0400 Subject: [PATCH] Adding Tests and Refactoring Functional Tests for RazorPages added --- .../Entities/BuyerAggregate/Buyer.cs | 9 +- .../Entities/OrderAggregate/Address.cs | 1 - .../OrderAggregate/CatalogItemOrdered.cs | 12 ++- .../Entities/OrderAggregate/Order.cs | 9 +- .../Entities/OrderAggregate/OrderItem.cs | 4 +- .../Exceptions/GuardExtensions.cs | 1 - .../Interfaces/IOrderService.cs | 1 - src/Infrastructure/Data/OrderRepository.cs | 4 +- src/Web/Controllers/OrderController.cs | 23 ----- src/Web/Startup.cs | 12 ++- tests/FunctionalTests/FunctionalTests.csproj | 1 + .../Controllers/ApiCatalogControllerList.cs | 18 +++- .../Web/Controllers/BaseWebTest.cs | 89 ------------------- .../Web/Controllers/CatalogControllerIndex.cs | 5 +- .../CustomWebApplicationFactory.cs | 8 +- .../Web/Controllers/OrderControllerIndex.cs | 32 +++++++ .../CustomWebRazorPagesApplicationFactory.cs | 70 +++++++++++++++ .../WebRazorPages/HomePageOnGet.cs | 29 ++++++ .../WebRazorPages/OrderIndexOnGet.cs | 32 +++++++ .../Entities/BasketTests/AddItem.cs | 2 +- .../Entities/OrderTests/Total.cs | 41 +++++++++ tests/UnitTests/Builders/OrderBuilder.cs | 14 ++- 22 files changed, 275 insertions(+), 142 deletions(-) delete mode 100644 tests/FunctionalTests/Web/Controllers/BaseWebTest.cs create mode 100644 tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs create mode 100644 tests/FunctionalTests/WebRazorPages/CustomWebRazorPagesApplicationFactory.cs create mode 100644 tests/FunctionalTests/WebRazorPages/HomePageOnGet.cs create mode 100644 tests/FunctionalTests/WebRazorPages/OrderIndexOnGet.cs create mode 100644 tests/UnitTests/ApplicationCore/Entities/OrderTests/Total.cs diff --git a/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs b/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs index 072e12c..f20b2c6 100644 --- a/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs +++ b/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs @@ -1,8 +1,7 @@ using ApplicationCore.Interfaces; +using Ardalis.GuardClauses; using Microsoft.eShopWeb.ApplicationCore.Entities; -using System; using System.Collections.Generic; -using System.Text; namespace ApplicationCore.Entities.BuyerAggregate { @@ -14,13 +13,15 @@ namespace ApplicationCore.Entities.BuyerAggregate public IEnumerable PaymentMethods => _paymentMethods.AsReadOnly(); - protected Buyer() + private Buyer() { + // required by EF } public Buyer(string identity) : this() { - IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity)); + Guard.Against.NullOrEmpty(identity, nameof(identity)); + IdentityGuid = identity; } } } diff --git a/src/ApplicationCore/Entities/OrderAggregate/Address.cs b/src/ApplicationCore/Entities/OrderAggregate/Address.cs index 8d214c0..85804b5 100644 --- a/src/ApplicationCore/Entities/OrderAggregate/Address.cs +++ b/src/ApplicationCore/Entities/OrderAggregate/Address.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace ApplicationCore.Entities.OrderAggregate { diff --git a/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs b/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs index 481c6b2..44df823 100644 --- a/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs +++ b/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs @@ -1,21 +1,29 @@ -namespace ApplicationCore.Entities.OrderAggregate +using Ardalis.GuardClauses; + +namespace ApplicationCore.Entities.OrderAggregate { /// - /// Represents the item that was ordered. If catalog item details change, details of + /// Represents a snapshot of the item that was ordered. If catalog item details change, details of /// the item that was part of a completed order should not change. /// public class CatalogItemOrdered // ValueObject { public CatalogItemOrdered(int catalogItemId, string productName, string pictureUri) { + Guard.Against.OutOfRange(catalogItemId, nameof(catalogItemId), 1, int.MaxValue); + Guard.Against.NullOrEmpty(productName, nameof(productName)); + Guard.Against.NullOrEmpty(pictureUri, nameof(pictureUri)); + CatalogItemId = catalogItemId; ProductName = productName; PictureUri = pictureUri; } + private CatalogItemOrdered() { // required by EF } + public int CatalogItemId { get; private set; } public string ProductName { get; private set; } public string PictureUri { get; private set; } diff --git a/src/ApplicationCore/Entities/OrderAggregate/Order.cs b/src/ApplicationCore/Entities/OrderAggregate/Order.cs index e99de40..171bb65 100644 --- a/src/ApplicationCore/Entities/OrderAggregate/Order.cs +++ b/src/ApplicationCore/Entities/OrderAggregate/Order.cs @@ -1,4 +1,5 @@ using ApplicationCore.Interfaces; +using Ardalis.GuardClauses; using Microsoft.eShopWeb.ApplicationCore.Entities; using System; using System.Collections.Generic; @@ -9,13 +10,18 @@ namespace ApplicationCore.Entities.OrderAggregate { private Order() { + // required by EF } public Order(string buyerId, Address shipToAddress, List items) { + Guard.Against.NullOrEmpty(buyerId, nameof(buyerId)); + Guard.Against.Null(shipToAddress, nameof(shipToAddress)); + Guard.Against.Null(items, nameof(items)); + + BuyerId = buyerId; ShipToAddress = shipToAddress; _orderItems = items; - BuyerId = buyerId; } public string BuyerId { get; private set; } @@ -43,6 +49,5 @@ namespace ApplicationCore.Entities.OrderAggregate } return total; } - } } diff --git a/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs b/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs index d63824b..773e3b1 100644 --- a/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs +++ b/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs @@ -9,9 +9,11 @@ namespace ApplicationCore.Entities.OrderAggregate public decimal UnitPrice { get; private set; } public int Units { get; private set; } - protected OrderItem() + private OrderItem() { + // required by EF } + public OrderItem(CatalogItemOrdered itemOrdered, decimal unitPrice, int units) { ItemOrdered = itemOrdered; diff --git a/src/ApplicationCore/Exceptions/GuardExtensions.cs b/src/ApplicationCore/Exceptions/GuardExtensions.cs index 5b3a84a..47c6508 100644 --- a/src/ApplicationCore/Exceptions/GuardExtensions.cs +++ b/src/ApplicationCore/Exceptions/GuardExtensions.cs @@ -1,5 +1,4 @@ using ApplicationCore.Exceptions; -using Microsoft.eShopWeb.ApplicationCore.Entities; using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate; namespace Ardalis.GuardClauses diff --git a/src/ApplicationCore/Interfaces/IOrderService.cs b/src/ApplicationCore/Interfaces/IOrderService.cs index 414f86d..3c37ab1 100644 --- a/src/ApplicationCore/Interfaces/IOrderService.cs +++ b/src/ApplicationCore/Interfaces/IOrderService.cs @@ -1,5 +1,4 @@ using ApplicationCore.Entities.OrderAggregate; -using System.Collections.Generic; using System.Threading.Tasks; namespace ApplicationCore.Interfaces diff --git a/src/Infrastructure/Data/OrderRepository.cs b/src/Infrastructure/Data/OrderRepository.cs index 35c5465..020fe47 100644 --- a/src/Infrastructure/Data/OrderRepository.cs +++ b/src/Infrastructure/Data/OrderRepository.cs @@ -16,7 +16,7 @@ namespace Infrastructure.Data { return _dbContext.Orders .Include(o => o.OrderItems) - .Include("OrderItems.ItemOrdered") + .Include($"{nameof(Order.OrderItems)}.{nameof(OrderItem.ItemOrdered)}") .FirstOrDefault(); } @@ -24,7 +24,7 @@ namespace Infrastructure.Data { return _dbContext.Orders .Include(o => o.OrderItems) - .Include("OrderItems.ItemOrdered") + .Include($"{nameof(Order.OrderItems)}.{nameof(OrderItem.ItemOrdered)}") .FirstOrDefaultAsync(); } } diff --git a/src/Web/Controllers/OrderController.cs b/src/Web/Controllers/OrderController.cs index 65ad091..db083f5 100644 --- a/src/Web/Controllers/OrderController.cs +++ b/src/Web/Controllers/OrderController.cs @@ -69,28 +69,5 @@ namespace Microsoft.eShopWeb.Controllers }; return View(viewModel); } - - private OrderViewModel GetOrder() - { - var order = new OrderViewModel() - { - OrderDate = DateTimeOffset.Now.AddDays(-1), - OrderNumber = 12354, - Status = "Submitted", - Total = 123.45m, - ShippingAddress = new Address("123 Main St.", "Kent", "OH", "United States", "44240") - }; - - order.OrderItems.Add(new OrderItemViewModel() - { - ProductId = 1, - PictureUrl = "", - ProductName = "Something", - UnitPrice = 5.05m, - Units = 2 - }); - - return order; - } } } diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs index edd33e2..50bd7da 100644 --- a/src/Web/Startup.cs +++ b/src/Web/Startup.cs @@ -31,13 +31,15 @@ namespace Microsoft.eShopWeb public void ConfigureDevelopmentServices(IServiceCollection services) { // use in-memory database - ConfigureTestingServices(services); + ConfigureInMemoryDatabases(services); // use real database // ConfigureProductionServices(services); + ConfigureServices(services); } - public void ConfigureTestingServices(IServiceCollection services) + + private void ConfigureInMemoryDatabases(IServiceCollection services) { // use in-memory database services.AddDbContext(c => @@ -46,8 +48,6 @@ namespace Microsoft.eShopWeb // Add Identity DbContext services.AddDbContext(options => options.UseInMemoryDatabase("Identity")); - - ConfigureServices(services); } public void ConfigureProductionServices(IServiceCollection services) @@ -86,6 +86,10 @@ namespace Microsoft.eShopWeb options.ExpireTimeSpan = TimeSpan.FromHours(1); options.LoginPath = "/Account/Signin"; options.LogoutPath = "/Account/Signout"; + options.Cookie = new CookieBuilder + { + IsEssential = true // required for auth to work without explicit user consent; adjust to suit your privacy policy + }; }); services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); diff --git a/tests/FunctionalTests/FunctionalTests.csproj b/tests/FunctionalTests/FunctionalTests.csproj index 6bb321f..6818edc 100644 --- a/tests/FunctionalTests/FunctionalTests.csproj +++ b/tests/FunctionalTests/FunctionalTests.csproj @@ -14,6 +14,7 @@ + diff --git a/tests/FunctionalTests/Web/Controllers/ApiCatalogControllerList.cs b/tests/FunctionalTests/Web/Controllers/ApiCatalogControllerList.cs index 10af990..74bd8be 100644 --- a/tests/FunctionalTests/Web/Controllers/ApiCatalogControllerList.cs +++ b/tests/FunctionalTests/Web/Controllers/ApiCatalogControllerList.cs @@ -1,17 +1,27 @@ -using Microsoft.eShopWeb.ViewModels; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.eShopWeb; +using Microsoft.eShopWeb.ViewModels; using Newtonsoft.Json; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using Xunit; namespace FunctionalTests.Web.Controllers { - public class ApiCatalogControllerList : BaseWebTest + public class ApiCatalogControllerList : IClassFixture> { + public ApiCatalogControllerList(CustomWebApplicationFactory factory) + { + Client = factory.CreateClient(); + } + + public HttpClient Client { get; } + [Fact] public async Task ReturnsFirst10CatalogItems() { - var response = await _client.GetAsync("/api/catalog/list"); + var response = await Client.GetAsync("/api/catalog/list"); response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); var model = JsonConvert.DeserializeObject(stringResponse); @@ -22,7 +32,7 @@ namespace FunctionalTests.Web.Controllers [Fact] public async Task ReturnsLast2CatalogItemsGivenPageIndex1() { - var response = await _client.GetAsync("/api/catalog/list?page=1"); + var response = await Client.GetAsync("/api/catalog/list?page=1"); response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); var model = JsonConvert.DeserializeObject(stringResponse); diff --git a/tests/FunctionalTests/Web/Controllers/BaseWebTest.cs b/tests/FunctionalTests/Web/Controllers/BaseWebTest.cs deleted file mode 100644 index f1c1d9f..0000000 --- a/tests/FunctionalTests/Web/Controllers/BaseWebTest.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.IO; -using System.Net.Http; -using System.Reflection; -using Microsoft.eShopWeb; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Logging; -using Infrastructure.Data; -using Infrastructure.Identity; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.DependencyInjection; - -namespace FunctionalTests.Web.Controllers -{ - public abstract class BaseWebTest - { - protected readonly HttpClient _client; - protected string _contentRoot; - - public BaseWebTest() - { - _client = GetClient(); - } - - protected HttpClient GetClient() - { - var startupAssembly = typeof(Startup).GetTypeInfo().Assembly; - _contentRoot = GetProjectPath("src", startupAssembly); - var builder = new WebHostBuilder() - .UseContentRoot(_contentRoot) - .UseEnvironment("Testing") - .UseStartup(); - - var server = new TestServer(builder); - - // seed data - using (var scope = server.Host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - var loggerFactory = services.GetRequiredService(); - var catalogContext = services.GetRequiredService(); - CatalogContextSeed.SeedAsync(catalogContext, loggerFactory) - .Wait(); - - var userManager = services.GetRequiredService>(); - AppIdentityDbContextSeed.SeedAsync(userManager).Wait(); - } - - return server.CreateClient(); - } - - /// - /// Gets the full path to the target project path that we wish to test - /// - /// - /// The parent directory of the target project. - /// e.g. src, samples, test, or test/Websites - /// - /// The target project's assembly. - /// The full path to the target project. - protected static string GetProjectPath(string solutionRelativePath, Assembly startupAssembly) - { - // Get name of the target project which we want to test - var projectName = startupAssembly.GetName().Name; - - // Get currently executing test project path - var applicationBasePath = AppContext.BaseDirectory; - - // Find the folder which contains the solution file. We then use this information to find the target - // project which we want to test. - var directoryInfo = new DirectoryInfo(applicationBasePath); - do - { - var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, "eShopOnWeb.sln")); - if (solutionFileInfo.Exists) - { - return Path.GetFullPath(Path.Combine(directoryInfo.FullName, solutionRelativePath, projectName)); - } - - directoryInfo = directoryInfo.Parent; - } - while (directoryInfo.Parent != null); - - throw new Exception($"Solution root could not be located using application root {applicationBasePath}."); - } - - } -} diff --git a/tests/FunctionalTests/Web/Controllers/CatalogControllerIndex.cs b/tests/FunctionalTests/Web/Controllers/CatalogControllerIndex.cs index 47d210e..18dd4bb 100644 --- a/tests/FunctionalTests/Web/Controllers/CatalogControllerIndex.cs +++ b/tests/FunctionalTests/Web/Controllers/CatalogControllerIndex.cs @@ -10,10 +10,7 @@ namespace FunctionalTests.Web.Controllers { public CatalogControllerIndex(CustomWebApplicationFactory factory) { - Client = factory.CreateClient(new WebApplicationFactoryClientOptions - { - AllowAutoRedirect = false - }); + Client = factory.CreateClient(); } public HttpClient Client { get; } diff --git a/tests/FunctionalTests/Web/Controllers/CustomWebApplicationFactory.cs b/tests/FunctionalTests/Web/Controllers/CustomWebApplicationFactory.cs index f0c80e6..ef2be86 100644 --- a/tests/FunctionalTests/Web/Controllers/CustomWebApplicationFactory.cs +++ b/tests/FunctionalTests/Web/Controllers/CustomWebApplicationFactory.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using Microsoft.EntityFrameworkCore; +using Infrastructure.Identity; namespace FunctionalTests.Web.Controllers { @@ -14,7 +15,6 @@ namespace FunctionalTests.Web.Controllers { protected override void ConfigureWebHost(IWebHostBuilder builder) { - builder.UseEnvironment("Testing"); builder.ConfigureServices(services => { // Create a new service provider. @@ -30,6 +30,12 @@ namespace FunctionalTests.Web.Controllers options.UseInternalServiceProvider(serviceProvider); }); + services.AddDbContext(options => + { + options.UseInMemoryDatabase("Identity"); + options.UseInternalServiceProvider(serviceProvider); + }); + // Build the service provider. var sp = services.BuildServiceProvider(); diff --git a/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs b/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs new file mode 100644 index 0000000..4cef8de --- /dev/null +++ b/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.eShopWeb; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace FunctionalTests.Web.Controllers +{ + public class OrderIndexOnGet : IClassFixture> + { + public OrderIndexOnGet(CustomWebApplicationFactory factory) + { + Client = factory.CreateClient(new WebApplicationFactoryClientOptions + { + AllowAutoRedirect = false + }); + } + + public HttpClient Client { get; } + + [Fact] + public async Task ReturnsRedirectGivenAnonymousUser() + { + var response = await Client.GetAsync("/Order/Index"); + var redirectLocation = response.Headers.Location.OriginalString; + + Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + Assert.Contains("Account/Signin", redirectLocation); + } + } +} diff --git a/tests/FunctionalTests/WebRazorPages/CustomWebRazorPagesApplicationFactory.cs b/tests/FunctionalTests/WebRazorPages/CustomWebRazorPagesApplicationFactory.cs new file mode 100644 index 0000000..c289cba --- /dev/null +++ b/tests/FunctionalTests/WebRazorPages/CustomWebRazorPagesApplicationFactory.cs @@ -0,0 +1,70 @@ +using Infrastructure.Data; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.eShopWeb; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using Microsoft.EntityFrameworkCore; +using Infrastructure.Identity; + +namespace FunctionalTests.WebRazorPages +{ + public class CustomWebRazorPagesApplicationFactory + : WebApplicationFactory + { + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.ConfigureServices(services => + { + // Create a new service provider. + var serviceProvider = new ServiceCollection() + .AddEntityFrameworkInMemoryDatabase() + .BuildServiceProvider(); + + // Add a database context (ApplicationDbContext) using an in-memory + // database for testing. + services.AddDbContext(options => + { + options.UseInMemoryDatabase("InMemoryDbForTesting"); + options.UseInternalServiceProvider(serviceProvider); + }); + + services.AddDbContext(options => + { + options.UseInMemoryDatabase("Identity"); + options.UseInternalServiceProvider(serviceProvider); + }); + + // Build the service provider. + var sp = services.BuildServiceProvider(); + + // Create a scope to obtain a reference to the database + // context (ApplicationDbContext). + using (var scope = sp.CreateScope()) + { + var scopedServices = scope.ServiceProvider; + var db = scopedServices.GetRequiredService(); + var loggerFactory = scopedServices.GetRequiredService(); + + var logger = scopedServices + .GetRequiredService>>(); + + // Ensure the database is created. + db.Database.EnsureCreated(); + + try + { + // Seed the database with test data. + CatalogContextSeed.SeedAsync(db, loggerFactory).Wait(); + } + catch (Exception ex) + { + logger.LogError(ex, $"An error occurred seeding the " + + "database with test messages. Error: {ex.Message}"); + } + } + }); + } + } +} diff --git a/tests/FunctionalTests/WebRazorPages/HomePageOnGet.cs b/tests/FunctionalTests/WebRazorPages/HomePageOnGet.cs new file mode 100644 index 0000000..5007d44 --- /dev/null +++ b/tests/FunctionalTests/WebRazorPages/HomePageOnGet.cs @@ -0,0 +1,29 @@ +using Microsoft.eShopWeb.RazorPages; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace FunctionalTests.WebRazorPages +{ + public class HomePageOnGet : IClassFixture> + { + public HomePageOnGet(CustomWebRazorPagesApplicationFactory factory) + { + Client = factory.CreateClient(); + } + + public HttpClient Client { get; } + + [Fact] + public async Task ReturnsHomePageWithProductListing() + { + // Arrange & Act + var response = await Client.GetAsync("/"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Contains(".NET Bot Black Sweatshirt", stringResponse); + } + } +} diff --git a/tests/FunctionalTests/WebRazorPages/OrderIndexOnGet.cs b/tests/FunctionalTests/WebRazorPages/OrderIndexOnGet.cs new file mode 100644 index 0000000..a32fc8a --- /dev/null +++ b/tests/FunctionalTests/WebRazorPages/OrderIndexOnGet.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.eShopWeb; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace FunctionalTests.WebRazorPages +{ + public class OrderIndexOnGet : IClassFixture> + { + public OrderIndexOnGet(CustomWebRazorPagesApplicationFactory factory) + { + Client = factory.CreateClient(new WebApplicationFactoryClientOptions + { + AllowAutoRedirect = false + }); + } + + public HttpClient Client { get; } + + [Fact] + public async Task ReturnsRedirectGivenAnonymousUser() + { + var response = await Client.GetAsync("/Order/Index"); + var redirectLocation = response.Headers.Location.OriginalString; + + Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); + Assert.Contains("Account/Signin", redirectLocation); + } + } +} diff --git a/tests/UnitTests/ApplicationCore/Entities/BasketTests/AddItem.cs b/tests/UnitTests/ApplicationCore/Entities/BasketTests/AddItem.cs index e07e302..9714872 100644 --- a/tests/UnitTests/ApplicationCore/Entities/BasketTests/AddItem.cs +++ b/tests/UnitTests/ApplicationCore/Entities/BasketTests/AddItem.cs @@ -5,7 +5,7 @@ using Xunit; namespace UnitTests.ApplicationCore.Entities.BasketTests { - public class AddItem + public class Total { private int _testCatalogItemId = 123; private decimal _testUnitPrice = 1.23m; diff --git a/tests/UnitTests/ApplicationCore/Entities/OrderTests/Total.cs b/tests/UnitTests/ApplicationCore/Entities/OrderTests/Total.cs new file mode 100644 index 0000000..469383f --- /dev/null +++ b/tests/UnitTests/ApplicationCore/Entities/OrderTests/Total.cs @@ -0,0 +1,41 @@ +using ApplicationCore.Entities.OrderAggregate; +using System.Collections.Generic; +using UnitTests.Builders; +using Xunit; + +namespace UnitTests.ApplicationCore.Entities.OrderTests +{ + public class Total + { + private decimal _testUnitPrice = 42m; + + [Fact] + public void IsZeroForNewOrder() + { + var order = new OrderBuilder().WithNoItems(); + + Assert.Equal(0, order.Total()); + } + + [Fact] + public void IsCorrectGiven1Item() + { + var builder = new OrderBuilder(); + var items = new List + { + new OrderItem(builder.TestCatalogItemOrdered, _testUnitPrice, 1) + }; + var order = new OrderBuilder().WithItems(items); + Assert.Equal(_testUnitPrice, order.Total()); + } + + [Fact] + public void IsCorrectGiven3Items() + { + var builder = new OrderBuilder(); + var order = builder.WithDefaultValues(); + + Assert.Equal(builder.TestUnitPrice * builder.TestUnits, order.Total()); + } + } +} diff --git a/tests/UnitTests/Builders/OrderBuilder.cs b/tests/UnitTests/Builders/OrderBuilder.cs index 05a9865..3ef552d 100644 --- a/tests/UnitTests/Builders/OrderBuilder.cs +++ b/tests/UnitTests/Builders/OrderBuilder.cs @@ -1,7 +1,5 @@ using ApplicationCore.Entities.OrderAggregate; -using System; using System.Collections.Generic; -using System.Text; namespace UnitTests.Builders { @@ -34,5 +32,17 @@ namespace UnitTests.Builders _order = new Order(TestBuyerId, new AddressBuilder().WithDefaultValues(), itemList); return _order; } + + public Order WithNoItems() + { + _order = new Order(TestBuyerId, new AddressBuilder().WithDefaultValues(), new List()); + return _order; + } + + public Order WithItems(List items) + { + _order = new Order(TestBuyerId, new AddressBuilder().WithDefaultValues(), items); + return _order; + } } }