@ -0,0 +1,26 @@ | |||||
using Microsoft.AspNetCore.Http; | |||||
using System.Security.Claims; | |||||
using System.Threading.Tasks; | |||||
namespace Basket.FunctionalTests.Base | |||||
{ | |||||
class AutoAuthorizeMiddleware | |||||
{ | |||||
private readonly RequestDelegate _next; | |||||
public AutoAuthorizeMiddleware(RequestDelegate rd) | |||||
{ | |||||
_next = rd; | |||||
} | |||||
public async Task Invoke(HttpContext httpContext) | |||||
{ | |||||
var identity = new ClaimsIdentity("cookies"); | |||||
identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00")); | |||||
httpContext.User.AddIdentity(identity); | |||||
await _next.Invoke(httpContext); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,38 @@ | |||||
using Microsoft.AspNetCore; | |||||
using Microsoft.AspNetCore.Hosting; | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System.Text; | |||||
namespace Basket.FunctionalTests.Base | |||||
{ | |||||
public class BasketScenarioBase | |||||
{ | |||||
private const string ApiUrlBase = "api/v1/basket"; | |||||
public TestServer CreateServer() | |||||
{ | |||||
var webHostBuilder = WebHost.CreateDefaultBuilder(); | |||||
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\basket"); | |||||
webHostBuilder.UseStartup<BasketTestsStartup>(); | |||||
return new TestServer(webHostBuilder); | |||||
} | |||||
public static class Get | |||||
{ | |||||
public static string GetBasket(int id) | |||||
{ | |||||
return $"{ApiUrlBase}/{id}"; | |||||
} | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string Basket = $"{ApiUrlBase}/"; | |||||
public static string CheckoutOrder = $"{ApiUrlBase}/checkout"; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
using Microsoft.AspNetCore.Builder; | |||||
using Microsoft.eShopOnContainers.Services.Basket.API; | |||||
using Microsoft.Extensions.Configuration; | |||||
namespace Basket.FunctionalTests.Base | |||||
{ | |||||
class BasketTestsStartup : Startup | |||||
{ | |||||
public BasketTestsStartup(IConfiguration env) : base(env) | |||||
{ | |||||
} | |||||
protected override void ConfigureAuth(IApplicationBuilder app) | |||||
{ | |||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) | |||||
{ | |||||
app.UseMiddleware<AutoAuthorizeMiddleware>(); | |||||
} | |||||
else | |||||
{ | |||||
base.ConfigureAuth(app); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,18 @@ | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using System; | |||||
using System.Net.Http; | |||||
namespace Basket.FunctionalTests.Base | |||||
{ | |||||
static class HttpClientExtensions | |||||
{ | |||||
public static HttpClient CreateIdempotentClient(this TestServer server) | |||||
{ | |||||
var client = server.CreateClient(); | |||||
client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); | |||||
return client; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,22 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | |||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.0" /> | |||||
<PackageReference Include="xunit" Version="2.3.1" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | |||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | |||||
<PackageReference Include="Moq" Version="4.8.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\Web\WebMVC\WebMVC.csproj" /> | |||||
<ProjectReference Include="..\..\src\Services\Basket\Basket.API\Basket.API.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@ -0,0 +1,94 @@ | |||||
using Basket.FunctionalTests.Base; | |||||
using Microsoft.eShopOnContainers.Services.Basket.API.Model; | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Net.Http; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using WebMVC.Models; | |||||
using Xunit; | |||||
namespace Basket.FunctionalTests | |||||
{ | |||||
public class BasketScenarios | |||||
: BasketScenarioBase | |||||
{ | |||||
[Fact] | |||||
public async Task Post_basket_and_response_ok_status_code() | |||||
{ | |||||
using (var server = CreateServer()) | |||||
{ | |||||
var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); | |||||
var response = await server.CreateClient() | |||||
.PostAsync(Post.Basket, content); | |||||
response.EnsureSuccessStatusCode(); | |||||
} | |||||
} | |||||
[Fact] | |||||
public async Task Get_basket_and_response_ok_status_code() | |||||
{ | |||||
using (var server = CreateServer()) | |||||
{ | |||||
var response = await server.CreateClient() | |||||
.GetAsync(Get.GetBasket(1)); | |||||
response.EnsureSuccessStatusCode(); | |||||
} | |||||
} | |||||
[Fact] | |||||
public async Task Send_Checkout_basket_and_response_ok_status_code() | |||||
{ | |||||
using (var server = CreateServer()) | |||||
{ | |||||
var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); | |||||
await server.CreateClient() | |||||
.PostAsync(Post.Basket, contentBasket); | |||||
var contentCheckout = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); | |||||
var response = await server.CreateIdempotentClient() | |||||
.PostAsync(Post.CheckoutOrder, contentCheckout); | |||||
response.EnsureSuccessStatusCode(); | |||||
} | |||||
} | |||||
string BuildBasket() | |||||
{ | |||||
var order = new CustomerBasket("1234"); | |||||
order.Items.Add(new BasketItem | |||||
{ | |||||
ProductId = "1", | |||||
ProductName = ".NET Bot Black Hoodie", | |||||
UnitPrice = 10, | |||||
Quantity = 1 | |||||
}); | |||||
return JsonConvert.SerializeObject(order); | |||||
} | |||||
string BuildCheckout() | |||||
{ | |||||
var checkoutBasket = new BasketDTO() | |||||
{ | |||||
City = "city", | |||||
Street = "street", | |||||
State = "state", | |||||
Country = "coutry", | |||||
ZipCode = "zipcode", | |||||
CardNumber = "1234567890123456", | |||||
CardHolderName = "CardHolderName", | |||||
CardExpiration = DateTime.UtcNow.AddDays(1), | |||||
CardSecurityNumber = "123", | |||||
CardTypeId = 1, | |||||
Buyer = "Buyer", | |||||
RequestId = Guid.NewGuid() | |||||
}; | |||||
return JsonConvert.SerializeObject(checkoutBasket); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,78 @@ | |||||
using Microsoft.eShopOnContainers.Services.Basket.API; | |||||
using Microsoft.Extensions.Options; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
namespace Basket.FunctionalTests | |||||
{ | |||||
//public class RedisBasketRepositoryTests | |||||
//{ | |||||
// private Mock<IOptionsSnapshot<BasketSettings>> _optionsMock; | |||||
// public RedisBasketRepositoryTests() | |||||
// { | |||||
// _optionsMock = new Mock<IOptionsSnapshot<BasketSettings>>(); | |||||
// } | |||||
// [Fact] | |||||
// public async Task UpdateBasket_return_and_add_basket() | |||||
// { | |||||
// var redisBasketRepository = BuildBasketRepository(); | |||||
// var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") | |||||
// { | |||||
// BuyerId = "buyerId", | |||||
// Items = BuildBasketItems() | |||||
// }); | |||||
// Assert.NotNull(basket); | |||||
// Assert.Single(basket.Items); | |||||
// } | |||||
// [Fact] | |||||
// public async Task Delete_Basket_return_null() | |||||
// { | |||||
// var redisBasketRepository = BuildBasketRepository(); | |||||
// var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") | |||||
// { | |||||
// BuyerId = "buyerId", | |||||
// Items = BuildBasketItems() | |||||
// }); | |||||
// var deleteResult = await redisBasketRepository.DeleteBasketAsync("buyerId"); | |||||
// var result = await redisBasketRepository.GetBasketAsync(basket.BuyerId); | |||||
// Assert.True(deleteResult); | |||||
// Assert.Null(result); | |||||
// } | |||||
// RedisBasketRepository BuildBasketRepository() | |||||
// { | |||||
// var loggerFactory = new LoggerFactory(); | |||||
// var configuration = ConfigurationOptions.Parse("127.0.0.1", true); | |||||
// configuration.ResolveDns = true; | |||||
// return new RedisBasketRepository(loggerFactory, ConnectionMultiplexer.Connect(configuration)); | |||||
// } | |||||
// List<BasketItem> BuildBasketItems() | |||||
// { | |||||
// return new List<BasketItem>() | |||||
// { | |||||
// new BasketItem() | |||||
// { | |||||
// Id = "basketId", | |||||
// PictureUrl = "pictureurl", | |||||
// ProductId = "productId", | |||||
// ProductName = "productName", | |||||
// Quantity = 1, | |||||
// UnitPrice = 1 | |||||
// } | |||||
// }; | |||||
// } | |||||
//} | |||||
} |
@ -0,0 +1,15 @@ | |||||
{ | |||||
"Logging": { | |||||
"IncludeScopes": false, | |||||
"LogLevel": { | |||||
"Default": "Debug", | |||||
"System": "Information", | |||||
"Microsoft": "Information" | |||||
} | |||||
}, | |||||
"IdentityUrl": "http://localhost:5105", | |||||
"ConnectionString": "127.0.0.1", | |||||
"isTest": "true", | |||||
"EventBusConnection": "localhost", | |||||
"SubscriptionClientName": "Basket" | |||||
} |
@ -0,0 +1,116 @@ | |||||
using Basket.API.IntegrationEvents.Events; | |||||
using Basket.API.Model; | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||||
using Microsoft.eShopOnContainers.Services.Basket.API.Controllers; | |||||
using Microsoft.eShopOnContainers.Services.Basket.API.Model; | |||||
using Moq; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
using IBasketIdentityService = Microsoft.eShopOnContainers.Services.Basket.API.Services.IIdentityService; | |||||
namespace UnitTest.Basket.Application | |||||
{ | |||||
public class BasketWebApiTest | |||||
{ | |||||
private readonly Mock<IBasketRepository> _basketRepositoryMock; | |||||
private readonly Mock<IBasketIdentityService> _identityServiceMock; | |||||
private readonly Mock<IEventBus> _serviceBusMock; | |||||
public BasketWebApiTest() | |||||
{ | |||||
_basketRepositoryMock = new Mock<IBasketRepository>(); | |||||
_identityServiceMock = new Mock<IBasketIdentityService>(); | |||||
_serviceBusMock = new Mock<IEventBus>(); | |||||
} | |||||
[Fact] | |||||
public async Task Get_customer_basket_success() | |||||
{ | |||||
//Arrange | |||||
var fakeCustomerId = "1"; | |||||
var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); | |||||
_basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny<string>())) | |||||
.Returns(Task.FromResult(fakeCustomerBasket)); | |||||
_identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); | |||||
_serviceBusMock.Setup(x => x.Publish(It.IsAny<UserCheckoutAcceptedIntegrationEvent>())); | |||||
//Act | |||||
var basketController = new BasketController( | |||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); | |||||
var actionResult = await basketController.Get(fakeCustomerId) as OkObjectResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId); | |||||
} | |||||
[Fact] | |||||
public async Task Post_customer_basket_success() | |||||
{ | |||||
//Arrange | |||||
var fakeCustomerId = "1"; | |||||
var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); | |||||
_basketRepositoryMock.Setup(x => x.UpdateBasketAsync(It.IsAny<CustomerBasket>())) | |||||
.Returns(Task.FromResult(fakeCustomerBasket)); | |||||
_identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); | |||||
_serviceBusMock.Setup(x => x.Publish(It.IsAny<UserCheckoutAcceptedIntegrationEvent>())); | |||||
//Act | |||||
var basketController = new BasketController( | |||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); | |||||
var actionResult = await basketController.Post(fakeCustomerBasket) as OkObjectResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
Assert.Equal(((CustomerBasket)actionResult.Value).BuyerId, fakeCustomerId); | |||||
} | |||||
[Fact] | |||||
public async Task Doing_Checkout_Without_Basket_Should_Return_Bad_Request() | |||||
{ | |||||
var fakeCustomerId = "2"; | |||||
_basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny<string>())) | |||||
.Returns(Task.FromResult((CustomerBasket)null)); | |||||
_identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); | |||||
//Act | |||||
var basketController = new BasketController( | |||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); | |||||
var result = await basketController.Checkout(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult; | |||||
Assert.NotNull(result); | |||||
} | |||||
[Fact] | |||||
public async Task Doing_Checkout_Wit_Basket_Should_Publish_UserCheckoutAccepted_Integration_Event() | |||||
{ | |||||
var fakeCustomerId = "1"; | |||||
var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); | |||||
_basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny<string>())) | |||||
.Returns(Task.FromResult(fakeCustomerBasket)); | |||||
_identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); | |||||
//Act | |||||
var basketController = new BasketController( | |||||
_basketRepositoryMock.Object, _identityServiceMock.Object, _serviceBusMock.Object); | |||||
var result = await basketController.Checkout(new BasketCheckout(), Guid.NewGuid().ToString()) as AcceptedResult; | |||||
_serviceBusMock.Verify(mock => mock.Publish(It.IsAny<UserCheckoutAcceptedIntegrationEvent>()), Times.Once); | |||||
Assert.NotNull(result); | |||||
} | |||||
private CustomerBasket GetCustomerBasketFake(string fakeCustomerId) | |||||
{ | |||||
return new CustomerBasket(fakeCustomerId) | |||||
{ | |||||
Items = new List<BasketItem>() | |||||
{ | |||||
new BasketItem() | |||||
} | |||||
}; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,130 @@ | |||||
using Microsoft.AspNetCore.Http; | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.WebMVC.Controllers; | |||||
using Microsoft.eShopOnContainers.WebMVC.Services; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||||
using Moq; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; | |||||
namespace UnitTest.Basket.Application | |||||
{ | |||||
public class CartControllerTest | |||||
{ | |||||
private readonly Mock<ICatalogService> _catalogServiceMock; | |||||
private readonly Mock<IBasketService> _basketServiceMock; | |||||
private readonly Mock<IIdentityParser<ApplicationUser>> _identityParserMock; | |||||
private readonly Mock<HttpContext> _contextMock; | |||||
public CartControllerTest() | |||||
{ | |||||
_catalogServiceMock = new Mock<ICatalogService>(); | |||||
_basketServiceMock = new Mock<IBasketService>(); | |||||
_identityParserMock = new Mock<IIdentityParser<ApplicationUser>>(); | |||||
_contextMock = new Mock<HttpContext>(); | |||||
} | |||||
[Fact] | |||||
public async Task Post_cart_success() | |||||
{ | |||||
//Arrange | |||||
var fakeBuyerId = "1"; | |||||
var action = string.Empty; | |||||
var fakeBasket = GetFakeBasket(fakeBuyerId); | |||||
var fakeQuantities = new Dictionary<string, int>() | |||||
{ | |||||
["fakeProdA"] = 1, | |||||
["fakeProdB"] = 2 | |||||
}; | |||||
_basketServiceMock.Setup(x => x.SetQuantities(It.IsAny<ApplicationUser>(), It.IsAny<Dictionary<string, int>>())) | |||||
.Returns(Task.FromResult(fakeBasket)); | |||||
_basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny<BasketModel>())) | |||||
.Returns(Task.FromResult(fakeBasket)); | |||||
//Act | |||||
var cartController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); | |||||
cartController.ControllerContext.HttpContext = _contextMock.Object; | |||||
var actionResult = await cartController.Index(fakeQuantities, action); | |||||
//Assert | |||||
var viewResult = Assert.IsType<ViewResult>(actionResult); | |||||
} | |||||
[Fact] | |||||
public async Task Post_cart_checkout_success() | |||||
{ | |||||
//Arrange | |||||
var fakeBuyerId = "1"; | |||||
var action = "[ Checkout ]"; | |||||
var fakeBasket = GetFakeBasket(fakeBuyerId); | |||||
var fakeQuantities = new Dictionary<string, int>() | |||||
{ | |||||
["fakeProdA"] = 1, | |||||
["fakeProdB"] = 2 | |||||
}; | |||||
_basketServiceMock.Setup(x => x.SetQuantities(It.IsAny<ApplicationUser>(), It.IsAny<Dictionary<string, int>>())) | |||||
.Returns(Task.FromResult(fakeBasket)); | |||||
_basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny<BasketModel>())) | |||||
.Returns(Task.FromResult(fakeBasket)); | |||||
//Act | |||||
var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); | |||||
orderController.ControllerContext.HttpContext = _contextMock.Object; | |||||
var actionResult = await orderController.Index(fakeQuantities, action); | |||||
//Assert | |||||
var redirectToActionResult = Assert.IsType<RedirectToActionResult>(actionResult); | |||||
Assert.Equal("Order", redirectToActionResult.ControllerName); | |||||
Assert.Equal("Create", redirectToActionResult.ActionName); | |||||
} | |||||
[Fact] | |||||
public async Task Add_to_cart_success() | |||||
{ | |||||
//Arrange | |||||
var fakeCatalogItem = GetFakeCatalogItem(); | |||||
_basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny<ApplicationUser>(), It.IsAny<Int32>())) | |||||
.Returns(Task.FromResult(1)); | |||||
//Act | |||||
var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); | |||||
orderController.ControllerContext.HttpContext = _contextMock.Object; | |||||
var actionResult = await orderController.AddToCart(fakeCatalogItem); | |||||
//Assert | |||||
var redirectToActionResult = Assert.IsType<RedirectToActionResult>(actionResult); | |||||
Assert.Equal("Catalog", redirectToActionResult.ControllerName); | |||||
Assert.Equal("Index", redirectToActionResult.ActionName); | |||||
} | |||||
private BasketModel GetFakeBasket(string buyerId) | |||||
{ | |||||
return new BasketModel() | |||||
{ | |||||
BuyerId = buyerId | |||||
}; | |||||
} | |||||
private CatalogItem GetFakeCatalogItem() | |||||
{ | |||||
return new CatalogItem() | |||||
{ | |||||
Id = 1, | |||||
Name = "fakeName", | |||||
CatalogBrand = "fakeBrand", | |||||
CatalogType = "fakeType", | |||||
CatalogBrandId = 2, | |||||
CatalogTypeId = 5, | |||||
Price = 20 | |||||
}; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,23 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | |||||
<PackageReference Include="xunit" Version="2.3.1" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | |||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | |||||
<PackageReference Include="MediatR" Version="4.1.0" /> | |||||
<PackageReference Include="Moq" Version="4.8.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\Services\Basket\Basket.API\Basket.API.csproj" /> | |||||
<ProjectReference Include="..\..\src\Web\WebMVC\WebMVC.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@ -0,0 +1,90 @@ | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.WebMVC.Controllers; | |||||
using Microsoft.eShopOnContainers.WebMVC.Services; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels; | |||||
using Moq; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
using CatalogModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Catalog; | |||||
namespace UnitTest.Catalog.Application | |||||
{ | |||||
public class CatalogControllerTest | |||||
{ | |||||
private readonly Mock<ICatalogService> _catalogServiceMock; | |||||
public CatalogControllerTest() | |||||
{ | |||||
_catalogServiceMock = new Mock<ICatalogService>(); | |||||
} | |||||
[Fact] | |||||
public async Task Get_catalog_items_success() | |||||
{ | |||||
//Arrange | |||||
var fakeBrandFilterApplied = 1; | |||||
var fakeTypesFilterApplied = 2; | |||||
var fakePage = 2; | |||||
var fakeCatalog = GetFakeCatalog(); | |||||
var expectedNumberOfPages = 5; | |||||
var expectedTotalPages = 50; | |||||
var expectedCurrentPage = 2; | |||||
_catalogServiceMock.Setup(x => x.GetCatalogItems | |||||
( | |||||
It.Is<int>(y => y == fakePage), | |||||
It.IsAny<int>(), | |||||
It.Is<int?>(y => y == fakeBrandFilterApplied), | |||||
It.Is<int?>(y => y == fakeTypesFilterApplied) | |||||
)) | |||||
.Returns(Task.FromResult(fakeCatalog)); | |||||
//Act | |||||
var orderController = new CatalogController(_catalogServiceMock.Object); | |||||
var actionResult = await orderController.Index(fakeBrandFilterApplied, fakeTypesFilterApplied, fakePage, null); | |||||
//Assert | |||||
var viewResult = Assert.IsType<ViewResult>(actionResult); | |||||
var model = Assert.IsAssignableFrom<IndexViewModel>(viewResult.ViewData.Model); | |||||
Assert.Equal(model.PaginationInfo.TotalPages, expectedNumberOfPages); | |||||
Assert.Equal(model.PaginationInfo.TotalItems, expectedTotalPages); | |||||
Assert.Equal(model.PaginationInfo.ActualPage, expectedCurrentPage); | |||||
Assert.Empty(model.PaginationInfo.Next); | |||||
Assert.Empty(model.PaginationInfo.Previous); | |||||
} | |||||
private CatalogModel GetFakeCatalog() | |||||
{ | |||||
return new CatalogModel() | |||||
{ | |||||
PageSize = 10, | |||||
Count = 50, | |||||
PageIndex = 2, | |||||
Data = new List<CatalogItem>() | |||||
{ | |||||
new CatalogItem() | |||||
{ | |||||
Id = 1, | |||||
Name = "fakeItemA", | |||||
CatalogTypeId = 1 | |||||
}, | |||||
new CatalogItem() | |||||
{ | |||||
Id = 2, | |||||
Name = "fakeItemB", | |||||
CatalogTypeId = 1 | |||||
}, | |||||
new CatalogItem() | |||||
{ | |||||
Id = 3, | |||||
Name = "fakeItemC", | |||||
CatalogTypeId = 1 | |||||
} | |||||
} | |||||
}; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,22 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | |||||
<PackageReference Include="xunit" Version="2.3.1" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | |||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | |||||
<PackageReference Include="Moq" Version="4.8.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\Services\Catalog\Catalog.API\Catalog.API.csproj" /> | |||||
<ProjectReference Include="..\..\src\Web\WebMVC\WebMVC.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@ -0,0 +1,26 @@ | |||||
using Microsoft.AspNetCore.Http; | |||||
using System.Security.Claims; | |||||
using System.Threading.Tasks; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
class AutoAuthorizeMiddleware | |||||
{ | |||||
private readonly RequestDelegate _next; | |||||
public AutoAuthorizeMiddleware(RequestDelegate rd) | |||||
{ | |||||
_next = rd; | |||||
} | |||||
public async Task Invoke(HttpContext httpContext) | |||||
{ | |||||
var identity = new ClaimsIdentity("cookies"); | |||||
identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00")); | |||||
httpContext.User.AddIdentity(identity); | |||||
await _next.Invoke(httpContext); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,37 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class CampaignScenariosBase : MarketingScenariosBase | |||||
{ | |||||
public static class Get | |||||
{ | |||||
public static string Campaigns = CampaignsUrlBase; | |||||
public static string CampaignBy(int id) | |||||
=> $"{CampaignsUrlBase}/{id}"; | |||||
public static string UserCampaignsByUserId() | |||||
=> $"{CampaignsUrlBase}/user"; | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string AddNewCampaign = CampaignsUrlBase; | |||||
} | |||||
public static class Put | |||||
{ | |||||
public static string CampaignBy(int id) | |||||
=> $"{CampaignsUrlBase}/{id}"; | |||||
} | |||||
public static class Delete | |||||
{ | |||||
public static string CampaignBy(int id) | |||||
=> $"{CampaignsUrlBase}/{id}"; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,37 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class CampaignScenariosBase : MarketingScenariosBase | |||||
{ | |||||
public static class Get | |||||
{ | |||||
public static string Campaigns = CampaignsUrlBase; | |||||
public static string CampaignBy(int id) | |||||
=> $"{CampaignsUrlBase}/{id}"; | |||||
public static string UserCampaignsByUserId() | |||||
=> $"{CampaignsUrlBase}/user"; | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string AddNewCampaign = CampaignsUrlBase; | |||||
} | |||||
public static class Put | |||||
{ | |||||
public static string CampaignBy(int id) | |||||
=> $"{CampaignsUrlBase}/{id}"; | |||||
} | |||||
public static class Delete | |||||
{ | |||||
public static string CampaignBy(int id) | |||||
=> $"{CampaignsUrlBase}/{id}"; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,40 @@ | |||||
using Microsoft.AspNetCore; | |||||
using Microsoft.AspNetCore.Hosting; | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using System; | |||||
using System.IO; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class LocationsScenariosBase | |||||
{ | |||||
public TestServer CreateServer() | |||||
{ | |||||
var webHostBuilder = WebHost.CreateDefaultBuilder(); | |||||
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Location"); | |||||
webHostBuilder.UseStartup<LocationsTestsStartup>(); | |||||
return new TestServer(webHostBuilder); | |||||
} | |||||
public static class Get | |||||
{ | |||||
public static string Locations = "api/v1/locations"; | |||||
public static string LocationBy(string id) | |||||
{ | |||||
return $"api/v1/locations/{id}"; | |||||
} | |||||
public static string UserLocationBy(Guid id) | |||||
{ | |||||
return $"api/v1/locations/user/{id}"; | |||||
} | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string AddNewLocation = "api/v1/locations/"; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,44 @@ | |||||
using Microsoft.AspNetCore.Builder; | |||||
using Microsoft.eShopOnContainers.Services.Marketing.API; | |||||
using Microsoft.Extensions.Configuration; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class LocationsTestsStartup : Startup | |||||
{ | |||||
public LocationsTestsStartup(IConfiguration configuration) : base(configuration) | |||||
{ | |||||
} | |||||
protected override void ConfigureAuth(IApplicationBuilder app) | |||||
{ | |||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) | |||||
{ | |||||
app.UseMiddleware<AutoAuthorizeMiddleware>(); | |||||
} | |||||
else | |||||
{ | |||||
base.ConfigureAuth(app); | |||||
} | |||||
} | |||||
//class LocationAuthorizeMiddleware | |||||
//{ | |||||
// private readonly RequestDelegate _next; | |||||
// public LocationAuthorizeMiddleware(RequestDelegate rd) | |||||
// { | |||||
// _next = rd; | |||||
// } | |||||
// public async Task Invoke(HttpContext httpContext) | |||||
// { | |||||
// var identity = new ClaimsIdentity("cookies"); | |||||
// identity.AddClaim(new Claim("sub", "4611ce3f-380d-4db5-8d76-87a8689058ed")); | |||||
// httpContext.User.AddIdentity(identity); | |||||
// await _next.Invoke(httpContext); | |||||
// } | |||||
//} | |||||
} | |||||
} |
@ -0,0 +1,36 @@ | |||||
using Microsoft.AspNetCore; | |||||
using Microsoft.AspNetCore.Hosting; | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Microsoft.Extensions.Logging; | |||||
using System.IO; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class MarketingScenariosBase | |||||
{ | |||||
public static string CampaignsUrlBase => "api/v1/campaigns"; | |||||
public TestServer CreateServer() | |||||
{ | |||||
var webHostBuilder = WebHost.CreateDefaultBuilder(); | |||||
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Marketing"); | |||||
webHostBuilder.UseStartup<MarketingTestsStartup>(); | |||||
var testServer = new TestServer(webHostBuilder); | |||||
testServer.Host | |||||
.MigrateDbContext<MarketingContext>((context, services) => | |||||
{ | |||||
var logger = services.GetService<ILogger<MarketingContextSeed>>(); | |||||
new MarketingContextSeed() | |||||
.SeedAsync(context, logger) | |||||
.Wait(); | |||||
}); | |||||
return testServer; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,28 @@ | |||||
using Microsoft.AspNetCore.Builder; | |||||
using Microsoft.eShopOnContainers.Services.Marketing.API; | |||||
using Microsoft.Extensions.Configuration; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class MarketingTestsStartup : Startup | |||||
{ | |||||
public MarketingTestsStartup(IConfiguration configuration) : base(configuration) | |||||
{ | |||||
} | |||||
protected override void ConfigureAuth(IApplicationBuilder app) | |||||
{ | |||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) | |||||
{ | |||||
app.UseMiddleware<AutoAuthorizeMiddleware>(); | |||||
} | |||||
else | |||||
{ | |||||
base.ConfigureAuth(app); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,45 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace Marketing.FunctionalTests.Base | |||||
{ | |||||
public class UserLocationRoleScenariosBase : MarketingScenariosBase | |||||
{ | |||||
private const string EndpointLocationName = "locations"; | |||||
public static class Get | |||||
{ | |||||
public static string UserLocationRulesByCampaignId(int campaignId) | |||||
=> GetUserLocationRolesUrlBase(campaignId); | |||||
public static string UserLocationRuleByCampaignAndUserLocationRuleId(int campaignId, | |||||
int userLocationRuleId) | |||||
=> $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}"; | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string AddNewuserLocationRule(int campaignId) | |||||
=> GetUserLocationRolesUrlBase(campaignId); | |||||
} | |||||
public static class Put | |||||
{ | |||||
public static string UserLocationRoleBy(int campaignId, | |||||
int userLocationRuleId) | |||||
=> $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}"; | |||||
} | |||||
public static class Delete | |||||
{ | |||||
public static string UserLocationRoleBy(int campaignId, | |||||
int userLocationRuleId) | |||||
=> $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}"; | |||||
} | |||||
private static string GetUserLocationRolesUrlBase(int campaignId) | |||||
=> $"{CampaignsUrlBase}/{campaignId}/{EndpointLocationName}"; | |||||
} | |||||
} |
@ -0,0 +1,30 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<Compile Remove="Base\CampaignScenarioBase.cs" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | |||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.0" /> | |||||
<PackageReference Include="xunit" Version="2.3.1" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | |||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Include="Base\CampaignScenarioBase.cs" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\Services\Location\Locations.API\Locations.API.csproj" /> | |||||
<ProjectReference Include="..\..\src\Services\Marketing\Marketing.API\Marketing.API.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@ -0,0 +1,46 @@ | |||||
using Marketing.FunctionalTests.Base; | |||||
using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; | |||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto; | |||||
using Newtonsoft.Json; | |||||
using System.Collections.Generic; | |||||
using System.Net.Http; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
namespace Marketing.FunctionalTests | |||||
{ | |||||
public class MarketingScenarios : MarketingScenariosBase | |||||
{ | |||||
[Fact] | |||||
public async Task Set_new_user_location_and_get_location_campaign_by_user_id() | |||||
{ | |||||
using (var locationsServer = new LocationsScenariosBase().CreateServer()) | |||||
using (var marketingServer = new MarketingScenariosBase().CreateServer()) | |||||
{ | |||||
var location = new LocationRequest | |||||
{ | |||||
Longitude = -122.315752, | |||||
Latitude = 47.60461 | |||||
}; | |||||
var content = new StringContent(JsonConvert.SerializeObject(location), | |||||
Encoding.UTF8, "application/json"); | |||||
// GIVEN a new location of user is created | |||||
await locationsServer.CreateClient() | |||||
.PostAsync(LocationsScenariosBase.Post.AddNewLocation, content); | |||||
await Task.Delay(300); | |||||
//Get campaing from Marketing.API | |||||
var campaignsResponse = await marketingServer.CreateClient() | |||||
.GetAsync(CampaignScenariosBase.Get.Campaigns); | |||||
var responseBody = await campaignsResponse.Content.ReadAsStringAsync(); | |||||
var campaigns = JsonConvert.DeserializeObject<List<CampaignDTO>>(responseBody); | |||||
Assert.True(campaigns.Count > 0); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,12 @@ | |||||
{ | |||||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word", | |||||
"MongoConnectionString": "mongodb://localhost:27017", | |||||
"MongoDatabase": "MarketingDb", | |||||
"IdentityUrl": "http://localhost:5105", | |||||
"isTest": "true", | |||||
"EventBusConnection": "localhost", | |||||
"AzureServiceBusEnabled": false, | |||||
"SubscriptionClientName": "Marketing", | |||||
"PicBaseUrl": "http://localhost:5110/api/v1/campaigns/[0]/pic/", | |||||
"SubscriptionClientName": "Marketing" | |||||
} |
@ -0,0 +1,26 @@ | |||||
using Microsoft.AspNetCore.Http; | |||||
using System.Security.Claims; | |||||
using System.Threading.Tasks; | |||||
namespace Ordering.FunctionalTests.Base | |||||
{ | |||||
class AutoAuthorizeMiddleware | |||||
{ | |||||
private readonly RequestDelegate _next; | |||||
public AutoAuthorizeMiddleware(RequestDelegate rd) | |||||
{ | |||||
_next = rd; | |||||
} | |||||
public async Task Invoke(HttpContext httpContext) | |||||
{ | |||||
var identity = new ClaimsIdentity("cookies"); | |||||
identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00")); | |||||
httpContext.User.AddIdentity(identity); | |||||
await _next.Invoke(httpContext); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,35 @@ | |||||
using Microsoft.AspNetCore; | |||||
using Microsoft.AspNetCore.Hosting; | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using System.IO; | |||||
namespace Ordering.FunctionalTests.Base | |||||
{ | |||||
class BasketScenariosBase | |||||
{ | |||||
private const string ApiUrlBase = "api/v1/basket"; | |||||
public TestServer CreateServer() | |||||
{ | |||||
var webHostBuilder = WebHost.CreateDefaultBuilder(); | |||||
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Basket"); | |||||
webHostBuilder.UseStartup<BasketTestsStartup>(); | |||||
return new TestServer(webHostBuilder); | |||||
} | |||||
public static class Get | |||||
{ | |||||
public static string GetBasketByCustomer(string customerId) | |||||
{ | |||||
return $"{ApiUrlBase}/{customerId}"; | |||||
} | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string CreateBasket = $"{ApiUrlBase}/"; | |||||
public static string Checkout = $"{ApiUrlBase}/checkout"; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
using Microsoft.AspNetCore.Builder; | |||||
using Microsoft.eShopOnContainers.Services.Basket.API; | |||||
using Microsoft.Extensions.Configuration; | |||||
namespace Ordering.FunctionalTests.Base | |||||
{ | |||||
class BasketTestsStartup : Startup | |||||
{ | |||||
public BasketTestsStartup(IConfiguration configuration) : base(configuration) | |||||
{ | |||||
} | |||||
protected override void ConfigureAuth(IApplicationBuilder app) | |||||
{ | |||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) | |||||
{ | |||||
app.UseMiddleware<AutoAuthorizeMiddleware>(); | |||||
} | |||||
else | |||||
{ | |||||
base.ConfigureAuth(app); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,18 @@ | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using System; | |||||
using System.Net.Http; | |||||
namespace Ordering.FunctionalTests.Base | |||||
{ | |||||
static class HttpClientExtensions | |||||
{ | |||||
public static HttpClient CreateIdempotentClient(this TestServer server) | |||||
{ | |||||
var client = server.CreateClient(); | |||||
client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); | |||||
return client; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,75 @@ | |||||
using Microsoft.AspNetCore; | |||||
using Microsoft.AspNetCore.Hosting; | |||||
using Microsoft.AspNetCore.TestHost; | |||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||||
using Microsoft.Extensions.Configuration; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Microsoft.Extensions.Logging; | |||||
using Microsoft.Extensions.Options; | |||||
using System.IO; | |||||
namespace Ordering.FunctionalTests.Base | |||||
{ | |||||
public class OrderingScenariosBase | |||||
{ | |||||
public TestServer CreateServer() | |||||
{ | |||||
var webHostBuilder = WebHost.CreateDefaultBuilder(); | |||||
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Ordering"); | |||||
webHostBuilder.UseStartup<OrderingTestsStartup>(); | |||||
webHostBuilder.ConfigureAppConfiguration((builderContext, config) => | |||||
{ | |||||
config.AddJsonFile("settings.json"); | |||||
}); | |||||
var testServer = new TestServer(webHostBuilder); | |||||
testServer.Host | |||||
.MigrateDbContext<OrderingContext>((context, services) => | |||||
{ | |||||
var env = services.GetService<IHostingEnvironment>(); | |||||
var settings = services.GetService<IOptions<OrderingSettings>>(); | |||||
var logger = services.GetService<ILogger<OrderingContextSeed>>(); | |||||
new OrderingContextSeed() | |||||
.SeedAsync(context, env, settings, logger) | |||||
.Wait(); | |||||
}) | |||||
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { }); | |||||
return testServer; | |||||
} | |||||
public static class Get | |||||
{ | |||||
public static string Orders = "api/v1/orders"; | |||||
public static string OrderBy(int id) | |||||
{ | |||||
return $"api/v1/orders/{id}"; | |||||
} | |||||
} | |||||
public static class Post | |||||
{ | |||||
public static string AddNewOrder = "api/v1/orders/new"; | |||||
} | |||||
public static class Put | |||||
{ | |||||
public static string CancelOrder = "api/v1/orders/cancel"; | |||||
public static string ShipOrder = "api/v1/orders/ship"; | |||||
} | |||||
public static class Delete | |||||
{ | |||||
public static string OrderBy(int id) | |||||
{ | |||||
return $"api/v1/orders/{id}"; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
using Microsoft.AspNetCore.Builder; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API; | |||||
using Microsoft.Extensions.Configuration; | |||||
namespace Ordering.FunctionalTests.Base | |||||
{ | |||||
public class OrderingTestsStartup : Startup | |||||
{ | |||||
public OrderingTestsStartup(IConfiguration env) : base(env) | |||||
{ | |||||
} | |||||
protected override void ConfigureAuth(IApplicationBuilder app) | |||||
{ | |||||
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) | |||||
{ | |||||
app.UseMiddleware<AutoAuthorizeMiddleware>(); | |||||
} | |||||
else | |||||
{ | |||||
base.ConfigureAuth(app); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,29 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | |||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.0" /> | |||||
<PackageReference Include="xunit" Version="2.3.1" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | |||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\Services\Basket\Basket.API\Basket.API.csproj" /> | |||||
<ProjectReference Include="..\..\src\Services\Ordering\Ordering.API\Ordering.API.csproj" /> | |||||
<ProjectReference Include="..\..\src\Web\WebMVC\WebMVC.csproj" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Update="settings.json"> | |||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |||||
</None> | |||||
</ItemGroup> | |||||
</Project> |
@ -0,0 +1,185 @@ | |||||
using Microsoft.eShopOnContainers.Services.Basket.API.Model; | |||||
//using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||||
using Newtonsoft.Json; | |||||
using Ordering.FunctionalTests.Base; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Net; | |||||
using System.Net.Http; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using WebMVC.Models; | |||||
using Xunit; | |||||
namespace Ordering.FunctionalTests | |||||
{ | |||||
public class OrderingScenarios : OrderingScenariosBase | |||||
{ | |||||
[Fact] | |||||
public async Task Cancel_basket_and_check_order_status_cancelled() | |||||
{ | |||||
using (var orderServer = new OrderingScenariosBase().CreateServer()) | |||||
using (var basketServer = new BasketScenariosBase().CreateServer()) | |||||
{ | |||||
// Expected data | |||||
var cityExpected = $"city-{Guid.NewGuid()}"; | |||||
var orderStatusExpected = "cancelled"; | |||||
var basketClient = basketServer.CreateIdempotentClient(); | |||||
var orderClient = orderServer.CreateIdempotentClient(); | |||||
// GIVEN a basket is created | |||||
var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); | |||||
await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket); | |||||
// AND basket checkout is sent | |||||
await basketClient.PostAsync(BasketScenariosBase.Post.Checkout, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json")); | |||||
// WHEN Order is created in Ordering.api | |||||
var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient); | |||||
// AND Order is cancelled in Ordering.api | |||||
await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json")); | |||||
// AND the requested order is retrieved | |||||
var order = await TryGetNewOrderCreated(cityExpected, orderClient); | |||||
// THEN check status | |||||
Assert.Equal(orderStatusExpected, order.Status); | |||||
} | |||||
} | |||||
[Fact] | |||||
public async Task Get_get_all_stored_orders_and_response_ok_status_code() | |||||
{ | |||||
using (var server = CreateServer()) | |||||
{ | |||||
var response = await server.CreateClient() | |||||
.GetAsync(Get.Orders); | |||||
response.EnsureSuccessStatusCode(); | |||||
} | |||||
} | |||||
[Fact] | |||||
public async Task Cancel_order_no_order_created_bad_request_response() | |||||
{ | |||||
using (var server = CreateServer()) | |||||
{ | |||||
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); | |||||
var response = await server.CreateIdempotentClient() | |||||
.PutAsync(Put.CancelOrder, content); | |||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); | |||||
} | |||||
} | |||||
[Fact] | |||||
public async Task Ship_order_no_order_created_bad_request_response() | |||||
{ | |||||
using (var server = CreateServer()) | |||||
{ | |||||
var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); | |||||
var response = await server.CreateIdempotentClient() | |||||
.PutAsync(Put.ShipOrder, content); | |||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); | |||||
} | |||||
} | |||||
string BuildOrder() | |||||
{ | |||||
var order = new OrderDTO() | |||||
{ | |||||
OrderNumber = "-1" | |||||
}; | |||||
return JsonConvert.SerializeObject(order); | |||||
} | |||||
private async Task<Order> TryGetNewOrderCreated(string city, HttpClient orderClient) | |||||
{ | |||||
var counter = 0; | |||||
Order order = null; | |||||
while (counter < 20) | |||||
{ | |||||
//get the orders and verify that the new order has been created | |||||
var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders); | |||||
var orders = JsonConvert.DeserializeObject<List<Order>>(ordersGetResponse); | |||||
if (orders == null || orders.Count == 0) | |||||
{ | |||||
counter++; | |||||
await Task.Delay(100); | |||||
continue; | |||||
} | |||||
var lastOrder = orders.OrderByDescending(o => o.Date).First(); | |||||
int.TryParse(lastOrder.OrderNumber, out int id); | |||||
var orderDetails = await orderClient.GetStringAsync(OrderingScenariosBase.Get.OrderBy(id)); | |||||
order = JsonConvert.DeserializeObject<Order>(orderDetails); | |||||
if (IsOrderCreated(order, city)) | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
return order; | |||||
} | |||||
private bool IsOrderCreated(Order order, string city) | |||||
{ | |||||
return order.City == city; | |||||
} | |||||
string BuildBasket() | |||||
{ | |||||
var order = new CustomerBasket("9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"); | |||||
order.Items = new List<Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem>() | |||||
{ | |||||
new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem() | |||||
{ | |||||
Id = "1", | |||||
ProductName = "ProductName", | |||||
ProductId = "1", | |||||
UnitPrice = 10, | |||||
Quantity = 1 | |||||
} | |||||
}; | |||||
return JsonConvert.SerializeObject(order); | |||||
} | |||||
string BuildCancelOrder(string orderId) | |||||
{ | |||||
var order = new OrderDTO() | |||||
{ | |||||
OrderNumber = orderId | |||||
}; | |||||
return JsonConvert.SerializeObject(order); | |||||
} | |||||
string BuildCheckout(string cityExpected) | |||||
{ | |||||
var checkoutBasket = new BasketDTO() | |||||
{ | |||||
City = cityExpected, | |||||
Street = "street", | |||||
State = "state", | |||||
Country = "coutry", | |||||
ZipCode = "zipcode", | |||||
CardNumber = "1111111111111", | |||||
CardHolderName = "CardHolderName", | |||||
CardExpiration = DateTime.Now.AddYears(1), | |||||
CardSecurityNumber = "123", | |||||
CardTypeId = 1, | |||||
Buyer = "Buyer", | |||||
RequestId = Guid.NewGuid() | |||||
}; | |||||
return JsonConvert.SerializeObject(checkoutBasket); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,10 @@ | |||||
{ | |||||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", | |||||
"ExternalCatalogBaseUrl": "http://localhost:5101", | |||||
"IdentityUrl": "http://localhost:5105", | |||||
"isTest": "true", | |||||
"EventBusConnection": "localhost", | |||||
"CheckUpdateTime": "30000", | |||||
"GracePeriodTime": "1", | |||||
"SubscriptionClientName": "Ordering" | |||||
} |
@ -0,0 +1,91 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace UnitTest.Ordering.Application | |||||
{ | |||||
using global::Ordering.API.Application.Models; | |||||
using MediatR; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; | |||||
using Moq; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
public class IdentifiedCommandHandlerTest | |||||
{ | |||||
private readonly Mock<IRequestManager> _requestManager; | |||||
private readonly Mock<IMediator> _mediator; | |||||
public IdentifiedCommandHandlerTest() | |||||
{ | |||||
_requestManager = new Mock<IRequestManager>(); | |||||
_mediator = new Mock<IMediator>(); | |||||
} | |||||
[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)); | |||||
_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); | |||||
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()); | |||||
} | |||||
[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)); | |||||
_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); | |||||
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()); | |||||
} | |||||
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); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,94 @@ | |||||
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; | |||||
namespace UnitTest.Ordering.Application | |||||
{ | |||||
using global::Ordering.API.Application.Models; | |||||
using MediatR; | |||||
using System.Collections; | |||||
using System.Collections.Generic; | |||||
using Xunit; | |||||
using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; | |||||
public class NewOrderRequestHandlerTest | |||||
{ | |||||
private readonly Mock<IOrderRepository> _orderRepositoryMock; | |||||
private readonly Mock<IIdentityService> _identityServiceMock; | |||||
private readonly Mock<IMediator> _mediator; | |||||
public NewOrderRequestHandlerTest() | |||||
{ | |||||
_orderRepositoryMock = new Mock<IOrderRepository>(); | |||||
_identityServiceMock = new Mock<IIdentityService>(); | |||||
_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); | |||||
//Act | |||||
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.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); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,86 @@ | |||||
using Microsoft.AspNetCore.Http; | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.WebMVC.Controllers; | |||||
using Microsoft.eShopOnContainers.WebMVC.Services; | |||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels; | |||||
using Moq; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | |||||
using Xunit; | |||||
using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; | |||||
namespace UnitTest.Ordering.Application | |||||
{ | |||||
public class OrderControllerTest | |||||
{ | |||||
private readonly Mock<IOrderingService> _orderServiceMock; | |||||
private readonly Mock<IBasketService> _basketServiceMock; | |||||
private readonly Mock<IIdentityParser<ApplicationUser>> _identityParserMock; | |||||
private readonly Mock<HttpContext> _contextMock; | |||||
public OrderControllerTest() | |||||
{ | |||||
_orderServiceMock = new Mock<IOrderingService>(); | |||||
_basketServiceMock = new Mock<IBasketService>(); | |||||
_identityParserMock = new Mock<IIdentityParser<ApplicationUser>>(); | |||||
_contextMock = new Mock<HttpContext>(); | |||||
} | |||||
[Fact] | |||||
public async Task Get_order_list_success() | |||||
{ | |||||
//Arrange | |||||
var expectedTotalResults = 1; | |||||
var fakeOrder = GetFakeOrder(); | |||||
_orderServiceMock.Setup(x => x.GetMyOrders(It.IsAny<ApplicationUser>())) | |||||
.Returns(Task.FromResult(new List<Order>() { fakeOrder })); | |||||
//Act | |||||
var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); | |||||
orderController.ControllerContext.HttpContext = _contextMock.Object; | |||||
var actionResult = await orderController.Index(fakeOrder); | |||||
//Assert | |||||
var viewResult = Assert.IsType<ViewResult>(actionResult); | |||||
var model = Assert.IsAssignableFrom<List<Order>>(viewResult.ViewData.Model); | |||||
Assert.Equal(model.Count, expectedTotalResults); | |||||
} | |||||
[Fact] | |||||
public async Task Get_order_detail_success() | |||||
{ | |||||
//Arrange | |||||
var fakeOrderId = "12"; | |||||
var fakeOrder = GetFakeOrder(); | |||||
_orderServiceMock.Setup(x => x.GetOrder(It.IsAny<ApplicationUser>(), It.IsAny<string>())) | |||||
.Returns(Task.FromResult(fakeOrder)); | |||||
//Act | |||||
var orderController = new OrderController(_orderServiceMock.Object, _basketServiceMock.Object, _identityParserMock.Object); | |||||
orderController.ControllerContext.HttpContext = _contextMock.Object; | |||||
var actionResult = await orderController.Detail(fakeOrderId); | |||||
//Assert | |||||
var viewResult = Assert.IsType<ViewResult>(actionResult); | |||||
Assert.IsAssignableFrom<Order>(viewResult.ViewData.Model); | |||||
} | |||||
private Order GetFakeOrder() | |||||
{ | |||||
return new Order() | |||||
{ | |||||
OrderNumber = "1", | |||||
CardNumber = "12", | |||||
CardSecurityNumber = "1212", | |||||
Status = "Pending", | |||||
RequestId = Guid.NewGuid(), | |||||
CardExpiration = DateTime.Now.AddYears(1), | |||||
}; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,141 @@ | |||||
using MediatR; | |||||
using Microsoft.AspNetCore.Mvc; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; | |||||
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 | |||||
{ | |||||
private readonly Mock<IMediator> _mediatorMock; | |||||
private readonly Mock<IOrderQueries> _orderQueriesMock; | |||||
private readonly Mock<IIdentityService> _identityServiceMock; | |||||
public OrdersWebApiTest() | |||||
{ | |||||
_mediatorMock = new Mock<IMediator>(); | |||||
_orderQueriesMock = new Mock<IOrderQueries>(); | |||||
_identityServiceMock = new Mock<IIdentityService>(); | |||||
} | |||||
[Fact] | |||||
public async Task Create_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); | |||||
var actionResult = await orderController.CancelOrder(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); | |||||
var actionResult = await orderController.CancelOrder(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); | |||||
var actionResult = await orderController.ShipOrder(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); | |||||
var actionResult = await orderController.ShipOrder(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>(); | |||||
_orderQueriesMock.Setup(x => x.GetOrdersFromUserAsync(Guid.NewGuid())) | |||||
.Returns(Task.FromResult(fakeDynamicResult)); | |||||
//Act | |||||
var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object); | |||||
var actionResult = await orderController.GetOrders() as OkObjectResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.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); | |||||
var actionResult = await orderController.GetOrder(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); | |||||
var actionResult = await orderController.GetCardTypes() as OkObjectResult; | |||||
//Assert | |||||
Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,48 @@ | |||||
using System; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||||
namespace UnitTest.Ordering | |||||
{ | |||||
public class AddressBuilder | |||||
{ | |||||
public Address Build() | |||||
{ | |||||
return new Address("street", "city", "state", "country", "zipcode"); | |||||
} | |||||
} | |||||
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 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; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,132 @@ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||||
using Ordering.Domain.Exceptions; | |||||
using System; | |||||
using Xunit; | |||||
public class BuyerAggregateTest | |||||
{ | |||||
public BuyerAggregateTest() | |||||
{ } | |||||
[Fact] | |||||
public void Create_buyer_item_success() | |||||
{ | |||||
//Arrange | |||||
var identity = new Guid().ToString(); | |||||
var name = "fakeUser"; | |||||
//Act | |||||
var fakeBuyerItem = new Buyer(identity, name); | |||||
//Assert | |||||
Assert.NotNull(fakeBuyerItem); | |||||
} | |||||
[Fact] | |||||
public void Create_buyer_item_fail() | |||||
{ | |||||
//Arrange | |||||
var identity = string.Empty; | |||||
var name = "fakeUser"; | |||||
//Act - Assert | |||||
Assert.Throws<ArgumentNullException>(() => new Buyer(identity, name)); | |||||
} | |||||
[Fact] | |||||
public void add_payment_success() | |||||
{ | |||||
//Arrange | |||||
var cardTypeId = 1; | |||||
var alias = "fakeAlias"; | |||||
var cardNumber = "124"; | |||||
var securityNumber = "1234"; | |||||
var cardHolderName = "FakeHolderNAme"; | |||||
var expiration = DateTime.Now.AddYears(1); | |||||
var orderId = 1; | |||||
var name = "fakeUser"; | |||||
var identity = new Guid().ToString(); | |||||
var fakeBuyerItem = new Buyer(identity, name); | |||||
//Act | |||||
var result = fakeBuyerItem.VerifyOrAddPaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration, orderId); | |||||
//Assert | |||||
Assert.NotNull(result); | |||||
} | |||||
[Fact] | |||||
public void create_payment_method_success() | |||||
{ | |||||
//Arrange | |||||
var cardTypeId = 1; | |||||
var alias = "fakeAlias"; | |||||
var cardNumber = "124"; | |||||
var securityNumber = "1234"; | |||||
var cardHolderName = "FakeHolderNAme"; | |||||
var expiration = DateTime.Now.AddYears(1); | |||||
var fakePaymentMethod = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); | |||||
//Act | |||||
var result = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); | |||||
//Assert | |||||
Assert.NotNull(result); | |||||
} | |||||
[Fact] | |||||
public void create_payment_method_expiration_fail() | |||||
{ | |||||
//Arrange | |||||
var cardTypeId = 1; | |||||
var alias = "fakeAlias"; | |||||
var cardNumber = "124"; | |||||
var securityNumber = "1234"; | |||||
var cardHolderName = "FakeHolderNAme"; | |||||
var expiration = DateTime.Now.AddYears(-1); | |||||
//Act - Assert | |||||
Assert.Throws<OrderingDomainException>(() => new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration)); | |||||
} | |||||
[Fact] | |||||
public void payment_method_isEqualTo() | |||||
{ | |||||
//Arrange | |||||
var cardTypeId = 1; | |||||
var alias = "fakeAlias"; | |||||
var cardNumber = "124"; | |||||
var securityNumber = "1234"; | |||||
var cardHolderName = "FakeHolderNAme"; | |||||
var expiration = DateTime.Now.AddYears(1); | |||||
//Act | |||||
var fakePaymentMethod = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); | |||||
var result = fakePaymentMethod.IsEqualTo(cardTypeId, cardNumber, expiration); | |||||
//Assert | |||||
Assert.True(result); | |||||
} | |||||
[Fact] | |||||
public void Add_new_PaymentMethod_raises_new_event() | |||||
{ | |||||
//Arrange | |||||
var alias = "fakeAlias"; | |||||
var orderId = 1; | |||||
var cardTypeId = 5; | |||||
var cardNumber = "12"; | |||||
var cardSecurityNumber = "123"; | |||||
var cardHolderName = "FakeName"; | |||||
var cardExpiration = DateTime.Now.AddYears(1); | |||||
var expectedResult = 1; | |||||
var name = "fakeUser"; | |||||
//Act | |||||
var fakeBuyer = new Buyer(Guid.NewGuid().ToString(), name); | |||||
fakeBuyer.VerifyOrAddPaymentMethod(cardTypeId, alias, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration, orderId); | |||||
//Assert | |||||
Assert.Equal(fakeBuyer.DomainEvents.Count, expectedResult); | |||||
} | |||||
} |
@ -0,0 +1,180 @@ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||||
using Ordering.Domain.Events; | |||||
using Ordering.Domain.Exceptions; | |||||
using System; | |||||
using System.Linq; | |||||
using UnitTest.Ordering; | |||||
using Xunit; | |||||
public class OrderAggregateTest | |||||
{ | |||||
public OrderAggregateTest() | |||||
{ } | |||||
[Fact] | |||||
public void Create_order_item_success() | |||||
{ | |||||
//Arrange | |||||
var productId = 1; | |||||
var productName = "FakeProductName"; | |||||
var unitPrice = 12; | |||||
var discount = 15; | |||||
var pictureUrl = "FakeUrl"; | |||||
var units = 5; | |||||
//Act | |||||
var fakeOrderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); | |||||
//Assert | |||||
Assert.NotNull(fakeOrderItem); | |||||
} | |||||
[Fact] | |||||
public void Invalid_number_of_units() | |||||
{ | |||||
//Arrange | |||||
var productId = 1; | |||||
var productName = "FakeProductName"; | |||||
var unitPrice = 12; | |||||
var discount = 15; | |||||
var pictureUrl = "FakeUrl"; | |||||
var units = -1; | |||||
//Act - Assert | |||||
Assert.Throws<OrderingDomainException>(() => new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units)); | |||||
} | |||||
[Fact] | |||||
public void Invalid_total_of_order_item_lower_than_discount_applied() | |||||
{ | |||||
//Arrange | |||||
var productId = 1; | |||||
var productName = "FakeProductName"; | |||||
var unitPrice = 12; | |||||
var discount = 15; | |||||
var pictureUrl = "FakeUrl"; | |||||
var units = 1; | |||||
//Act - Assert | |||||
Assert.Throws<OrderingDomainException>(() => new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units)); | |||||
} | |||||
[Fact] | |||||
public void Invalid_discount_setting() | |||||
{ | |||||
//Arrange | |||||
var productId = 1; | |||||
var productName = "FakeProductName"; | |||||
var unitPrice = 12; | |||||
var discount = 15; | |||||
var pictureUrl = "FakeUrl"; | |||||
var units = 5; | |||||
//Act | |||||
var fakeOrderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); | |||||
//Assert | |||||
Assert.Throws<OrderingDomainException>(() => fakeOrderItem.SetNewDiscount(-1)); | |||||
} | |||||
[Fact] | |||||
public void Invalid_units_setting() | |||||
{ | |||||
//Arrange | |||||
var productId = 1; | |||||
var productName = "FakeProductName"; | |||||
var unitPrice = 12; | |||||
var discount = 15; | |||||
var pictureUrl = "FakeUrl"; | |||||
var units = 5; | |||||
//Act | |||||
var fakeOrderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); | |||||
//Assert | |||||
Assert.Throws<OrderingDomainException>(() => fakeOrderItem.AddUnits(-1)); | |||||
} | |||||
[Fact] | |||||
public void when_add_two_times_on_the_same_item_then_the_total_of_order_should_be_the_sum_of_the_two_items() | |||||
{ | |||||
var address = new AddressBuilder().Build(); | |||||
var order = new OrderBuilder(address) | |||||
.AddOne(1,"cup",10.0m,0,string.Empty) | |||||
.AddOne(1,"cup",10.0m,0,string.Empty) | |||||
.Build(); | |||||
Assert.Equal(20.0m, order.GetTotal()); | |||||
} | |||||
[Fact] | |||||
public void Add_new_Order_raises_new_event() | |||||
{ | |||||
//Arrange | |||||
var street = "fakeStreet"; | |||||
var city = "FakeCity"; | |||||
var state = "fakeState"; | |||||
var country = "fakeCountry"; | |||||
var zipcode = "FakeZipCode"; | |||||
var cardTypeId = 5; | |||||
var cardNumber = "12"; | |||||
var cardSecurityNumber = "123"; | |||||
var cardHolderName = "FakeName"; | |||||
var cardExpiration = DateTime.Now.AddYears(1); | |||||
var expectedResult = 1; | |||||
//Act | |||||
var fakeOrder = new Order("1", "fakeName", new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); | |||||
//Assert | |||||
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); | |||||
} | |||||
[Fact] | |||||
public void Add_event_Order_explicitly_raises_new_event() | |||||
{ | |||||
//Arrange | |||||
var street = "fakeStreet"; | |||||
var city = "FakeCity"; | |||||
var state = "fakeState"; | |||||
var country = "fakeCountry"; | |||||
var zipcode = "FakeZipCode"; | |||||
var cardTypeId = 5; | |||||
var cardNumber = "12"; | |||||
var cardSecurityNumber = "123"; | |||||
var cardHolderName = "FakeName"; | |||||
var cardExpiration = DateTime.Now.AddYears(1); | |||||
var expectedResult = 2; | |||||
//Act | |||||
var fakeOrder = new Order("1", "fakeName", new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); | |||||
fakeOrder.AddDomainEvent(new OrderStartedDomainEvent(fakeOrder, "fakeName", "1", cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration)); | |||||
//Assert | |||||
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); | |||||
} | |||||
[Fact] | |||||
public void Remove_event_Order_explicitly() | |||||
{ | |||||
//Arrange | |||||
var street = "fakeStreet"; | |||||
var city = "FakeCity"; | |||||
var state = "fakeState"; | |||||
var country = "fakeCountry"; | |||||
var zipcode = "FakeZipCode"; | |||||
var cardTypeId = 5; | |||||
var cardNumber = "12"; | |||||
var cardSecurityNumber = "123"; | |||||
var cardHolderName = "FakeName"; | |||||
var cardExpiration = DateTime.Now.AddYears(1); | |||||
var fakeOrder = new Order("1", "fakeName", new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); | |||||
var @fakeEvent = new OrderStartedDomainEvent(fakeOrder, "1", "fakeName", cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); | |||||
var expectedResult = 1; | |||||
//Act | |||||
fakeOrder.AddDomainEvent(@fakeEvent); | |||||
fakeOrder.RemoveDomainEvent(@fakeEvent); | |||||
//Assert | |||||
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.1</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | |||||
<PackageReference Include="xunit" Version="2.3.1" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | |||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" /> | |||||
<PackageReference Include="MediatR" Version="4.1.0" /> | |||||
<PackageReference Include="Moq" Version="4.8.1" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\Services\Ordering\Ordering.API\Ordering.API.csproj" /> | |||||
<ProjectReference Include="..\..\src\Services\Ordering\Ordering.Domain\Ordering.Domain.csproj" /> | |||||
<ProjectReference Include="..\..\src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.csproj" /> | |||||
<ProjectReference Include="..\..\src\Web\WebMVC\WebMVC.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |