Use cancellation token in repository and web fie system (http call can cancelled) (#471)

Co-authored-by: cmichel <cmichel@interparking.com>
This commit is contained in:
Cédric Michel
2020-11-30 18:21:19 +01:00
committed by GitHub
parent 2502e01efd
commit 6041a1f183
19 changed files with 95 additions and 97 deletions

View File

@@ -1,12 +1,9 @@
using System; using Ardalis.GuardClauses;
using Ardalis.GuardClauses;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using System.Collections.Generic; using System;
namespace Microsoft.eShopWeb.ApplicationCore.Entities namespace Microsoft.eShopWeb.ApplicationCore.Entities
{ {
public class CatalogItem : BaseEntity, IAggregateRoot public class CatalogItem : BaseEntity, IAggregateRoot
{ {
public string Name { get; private set; } public string Name { get; private set; }
@@ -18,11 +15,11 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities
public int CatalogBrandId { get; private set; } public int CatalogBrandId { get; private set; }
public CatalogBrand CatalogBrand { get; private set; } public CatalogBrand CatalogBrand { get; private set; }
public CatalogItem(int catalogTypeId, public CatalogItem(int catalogTypeId,
int catalogBrandId, int catalogBrandId,
string description, string description,
string name, string name,
decimal price, decimal price,
string pictureUri) string pictureUri)
{ {
CatalogTypeId = catalogTypeId; CatalogTypeId = catalogTypeId;

View File

@@ -1,20 +1,21 @@
using Ardalis.Specification; using Ardalis.Specification;
using Microsoft.eShopWeb.ApplicationCore.Entities; using Microsoft.eShopWeb.ApplicationCore.Entities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces namespace Microsoft.eShopWeb.ApplicationCore.Interfaces
{ {
public interface IAsyncRepository<T> where T : BaseEntity, IAggregateRoot public interface IAsyncRepository<T> where T : BaseEntity, IAggregateRoot
{ {
Task<T> GetByIdAsync(int id); Task<T> GetByIdAsync(int id, CancellationToken cancellationToken = default);
Task<IReadOnlyList<T>> ListAllAsync(); Task<IReadOnlyList<T>> ListAllAsync(CancellationToken cancellationToken = default);
Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec); Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec, CancellationToken cancellationToken = default);
Task<T> AddAsync(T entity); Task<T> AddAsync(T entity, CancellationToken cancellationToken = default);
Task UpdateAsync(T entity); Task UpdateAsync(T entity, CancellationToken cancellationToken = default);
Task DeleteAsync(T entity); Task DeleteAsync(T entity, CancellationToken cancellationToken = default);
Task<int> CountAsync(ISpecification<T> spec); Task<int> CountAsync(ISpecification<T> spec, CancellationToken cancellationToken = default);
Task<T> FirstAsync(ISpecification<T> spec); Task<T> FirstAsync(ISpecification<T> spec, CancellationToken cancellationToken = default);
Task<T> FirstOrDefaultAsync(ISpecification<T> spec); Task<T> FirstOrDefaultAsync(ISpecification<T> spec, CancellationToken cancellationToken = default);
} }
} }

View File

@@ -1,9 +1,10 @@
using System.Threading.Tasks; using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces namespace Microsoft.eShopWeb.ApplicationCore.Interfaces
{ {
public interface IFileSystem public interface IFileSystem
{ {
Task<bool> SavePicture(string pictureName, string pictureBase64); Task<bool> SavePicture(string pictureName, string pictureBase64, CancellationToken cancellationToken);
} }
} }

View File

@@ -5,6 +5,7 @@ using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.eShopWeb.Infrastructure.Data namespace Microsoft.eShopWeb.Infrastructure.Data
@@ -23,58 +24,59 @@ namespace Microsoft.eShopWeb.Infrastructure.Data
_dbContext = dbContext; _dbContext = dbContext;
} }
public virtual async Task<T> GetByIdAsync(int id) public virtual async Task<T> GetByIdAsync(int id, CancellationToken cancellationToken = default)
{ {
return await _dbContext.Set<T>().FindAsync(id); var keyValues = new object[] { id };
return await _dbContext.Set<T>().FindAsync(keyValues, cancellationToken);
} }
public async Task<IReadOnlyList<T>> ListAllAsync() public async Task<IReadOnlyList<T>> ListAllAsync(CancellationToken cancellationToken = default)
{ {
return await _dbContext.Set<T>().ToListAsync(); return await _dbContext.Set<T>().ToListAsync(cancellationToken);
} }
public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec) public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec, CancellationToken cancellationToken = default)
{ {
var specificationResult = ApplySpecification(spec); var specificationResult = ApplySpecification(spec);
return await specificationResult.ToListAsync(); return await specificationResult.ToListAsync(cancellationToken);
} }
public async Task<int> CountAsync(ISpecification<T> spec) public async Task<int> CountAsync(ISpecification<T> spec, CancellationToken cancellationToken = default)
{ {
var specificationResult = ApplySpecification(spec); var specificationResult = ApplySpecification(spec);
return await specificationResult.CountAsync(); return await specificationResult.CountAsync(cancellationToken);
} }
public async Task<T> AddAsync(T entity) public async Task<T> AddAsync(T entity, CancellationToken cancellationToken = default)
{ {
await _dbContext.Set<T>().AddAsync(entity); await _dbContext.Set<T>().AddAsync(entity);
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync(cancellationToken);
return entity; return entity;
} }
public async Task UpdateAsync(T entity) public async Task UpdateAsync(T entity, CancellationToken cancellationToken = default)
{ {
_dbContext.Entry(entity).State = EntityState.Modified; _dbContext.Entry(entity).State = EntityState.Modified;
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync(cancellationToken);
} }
public async Task DeleteAsync(T entity) public async Task DeleteAsync(T entity, CancellationToken cancellationToken = default)
{ {
_dbContext.Set<T>().Remove(entity); _dbContext.Set<T>().Remove(entity);
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync(cancellationToken);
} }
public async Task<T> FirstAsync(ISpecification<T> spec) public async Task<T> FirstAsync(ISpecification<T> spec, CancellationToken cancellationToken = default)
{ {
var specificationResult = ApplySpecification(spec); var specificationResult = ApplySpecification(spec);
return await specificationResult.FirstAsync(); return await specificationResult.FirstAsync(cancellationToken);
} }
public async Task<T> FirstOrDefaultAsync(ISpecification<T> spec) public async Task<T> FirstOrDefaultAsync(ISpecification<T> spec, CancellationToken cancellationToken = default)
{ {
var specificationResult = ApplySpecification(spec); var specificationResult = ApplySpecification(spec);
return await specificationResult.FirstOrDefaultAsync(); return await specificationResult.FirstOrDefaultAsync(cancellationToken);
} }
private IQueryable<T> ApplySpecification(ISpecification<T> spec) private IQueryable<T> ApplySpecification(ISpecification<T> spec)

View File

@@ -1,15 +1,16 @@
using System; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.Infrastructure.Data;
using System;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.Infrastructure.Data;
namespace Microsoft.eShopWeb.Infrastructure.Services namespace Microsoft.eShopWeb.Infrastructure.Services
{ {
public class WebFileSystem: IFileSystem public class WebFileSystem : IFileSystem
{ {
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
private readonly string _url; private readonly string _url;
@@ -22,9 +23,9 @@ namespace Microsoft.eShopWeb.Infrastructure.Services
_httpClient.DefaultRequestHeaders.Add("auth-key", AUTH_KEY); _httpClient.DefaultRequestHeaders.Add("auth-key", AUTH_KEY);
} }
public async Task<bool> SavePicture(string pictureName, string pictureBase64) public async Task<bool> SavePicture(string pictureName, string pictureBase64, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(pictureBase64) || !await UploadFile(pictureName, Convert.FromBase64String(pictureBase64))) if (string.IsNullOrEmpty(pictureBase64) || !await UploadFile(pictureName, Convert.FromBase64String(pictureBase64), cancellationToken))
{ {
return false; return false;
} }
@@ -32,26 +33,26 @@ namespace Microsoft.eShopWeb.Infrastructure.Services
return true; return true;
} }
private async Task<bool> UploadFile(string fileName, byte[] fileData) private async Task<bool> UploadFile(string fileName, byte[] fileData, CancellationToken cancellationToken)
{ {
if (!fileData.IsValidImage(fileName)) if (!fileData.IsValidImage(fileName))
{ {
return false; return false;
} }
return await UploadToWeb(fileName, fileData); return await UploadToWeb(fileName, fileData, cancellationToken);
} }
private async Task<bool> UploadToWeb(string fileName, byte[] fileData) private async Task<bool> UploadToWeb(string fileName, byte[] fileData, CancellationToken cancellationToken)
{ {
var request = new FileItem var request = new FileItem
{ {
DataBase64 = Convert.ToBase64String(fileData), DataBase64 = Convert.ToBase64String(fileData),
FileName = fileName FileName = fileName
}; };
var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
using var message = await _httpClient.PostAsync(_url, content); using var message = await _httpClient.PostAsync(_url, content, cancellationToken);
if (!message.IsSuccessStatusCode) if (!message.IsSuccessStatusCode)
{ {
return false; return false;

View File

@@ -33,7 +33,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogBrandEndpoints
{ {
var response = new ListCatalogBrandsResponse(); var response = new ListCatalogBrandsResponse();
var items = await _catalogBrandRepository.ListAllAsync(); var items = await _catalogBrandRepository.ListAllAsync(cancellationToken);
response.CatalogBrands.AddRange(items.Select(_mapper.Map<CatalogBrandDto>)); response.CatalogBrands.AddRange(items.Select(_mapper.Map<CatalogBrandDto>));

View File

@@ -1,12 +1,12 @@
using System.IO; using Ardalis.ApiEndpoints;
using System.Threading;
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.ApplicationCore.Entities; using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
using System.IO;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
@@ -39,15 +39,15 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
var newItem = new CatalogItem(request.CatalogTypeId, request.CatalogBrandId, request.Description, request.Name, request.Price, request.PictureUri); var newItem = new CatalogItem(request.CatalogTypeId, request.CatalogBrandId, request.Description, request.Name, request.Price, request.PictureUri);
newItem = await _itemRepository.AddAsync(newItem); newItem = await _itemRepository.AddAsync(newItem, cancellationToken);
if (newItem.Id != 0) if (newItem.Id != 0)
{ {
var picName = $"{newItem.Id}{Path.GetExtension(request.PictureName)}"; var picName = $"{newItem.Id}{Path.GetExtension(request.PictureName)}";
if (await _webFileSystem.SavePicture(picName, request.PictureBase64)) if (await _webFileSystem.SavePicture(picName, request.PictureBase64, cancellationToken))
{ {
newItem.UpdatePictureUri(picName); newItem.UpdatePictureUri(picName);
await _itemRepository.UpdateAsync(newItem); await _itemRepository.UpdateAsync(newItem, cancellationToken);
} }
} }
@@ -65,6 +65,6 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
return response; return response;
} }
} }
} }

View File

@@ -1,12 +1,11 @@
using System.Threading; using Ardalis.ApiEndpoints;
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.ApplicationCore.Constants;
using Microsoft.eShopWeb.ApplicationCore.Entities; using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
@@ -28,14 +27,14 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
OperationId = "catalog-items.Delete", OperationId = "catalog-items.Delete",
Tags = new[] { "CatalogItemEndpoints" }) Tags = new[] { "CatalogItemEndpoints" })
] ]
public override async Task<ActionResult<DeleteCatalogItemResponse>> HandleAsync([FromRoute]DeleteCatalogItemRequest request, CancellationToken cancellationToken) public override async Task<ActionResult<DeleteCatalogItemResponse>> HandleAsync([FromRoute] DeleteCatalogItemRequest request, CancellationToken cancellationToken)
{ {
var response = new DeleteCatalogItemResponse(request.CorrelationId()); var response = new DeleteCatalogItemResponse(request.CorrelationId());
var itemToDelete = await _itemRepository.GetByIdAsync(request.CatalogItemId); var itemToDelete = await _itemRepository.GetByIdAsync(request.CatalogItemId, cancellationToken);
if (itemToDelete is null) return NotFound(); if (itemToDelete is null) return NotFound();
await _itemRepository.DeleteAsync(itemToDelete); await _itemRepository.DeleteAsync(itemToDelete, cancellationToken);
return Ok(response); return Ok(response);
} }

View File

@@ -1,9 +1,9 @@
using System.Threading; using Ardalis.ApiEndpoints;
using Ardalis.ApiEndpoints;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.ApplicationCore.Entities; using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
@@ -30,7 +30,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
{ {
var response = new GetByIdCatalogItemResponse(request.CorrelationId()); var response = new GetByIdCatalogItemResponse(request.CorrelationId());
var item = await _itemRepository.GetByIdAsync(request.CatalogItemId); var item = await _itemRepository.GetByIdAsync(request.CatalogItemId, cancellationToken);
if (item is null) return NotFound(); if (item is null) return NotFound();
response.CatalogItem = new CatalogItemDto response.CatalogItem = new CatalogItemDto

View File

@@ -34,12 +34,12 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
OperationId = "catalog-items.ListPaged", OperationId = "catalog-items.ListPaged",
Tags = new[] { "CatalogItemEndpoints" }) Tags = new[] { "CatalogItemEndpoints" })
] ]
public override async Task<ActionResult<ListPagedCatalogItemResponse>> HandleAsync([FromQuery]ListPagedCatalogItemRequest request, CancellationToken cancellationToken) public override async Task<ActionResult<ListPagedCatalogItemResponse>> HandleAsync([FromQuery] ListPagedCatalogItemRequest request, CancellationToken cancellationToken)
{ {
var response = new ListPagedCatalogItemResponse(request.CorrelationId()); var response = new ListPagedCatalogItemResponse(request.CorrelationId());
var filterSpec = new CatalogFilterSpecification(request.CatalogBrandId, request.CatalogTypeId); var filterSpec = new CatalogFilterSpecification(request.CatalogBrandId, request.CatalogTypeId);
int totalItems = await _itemRepository.CountAsync(filterSpec); int totalItems = await _itemRepository.CountAsync(filterSpec, cancellationToken);
var pagedSpec = new CatalogFilterPaginatedSpecification( var pagedSpec = new CatalogFilterPaginatedSpecification(
skip: request.PageIndex * request.PageSize, skip: request.PageIndex * request.PageSize,
@@ -47,7 +47,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
brandId: request.CatalogBrandId, brandId: request.CatalogBrandId,
typeId: request.CatalogTypeId); typeId: request.CatalogTypeId);
var items = await _itemRepository.ListAsync(pagedSpec); var items = await _itemRepository.ListAsync(pagedSpec, cancellationToken);
response.CatalogItems.AddRange(items.Select(_mapper.Map<CatalogItemDto>)); response.CatalogItems.AddRange(items.Select(_mapper.Map<CatalogItemDto>));
foreach (CatalogItemDto item in response.CatalogItems) foreach (CatalogItemDto item in response.CatalogItems)

View File

@@ -37,7 +37,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
{ {
var response = new UpdateCatalogItemResponse(request.CorrelationId()); var response = new UpdateCatalogItemResponse(request.CorrelationId());
var existingItem = await _itemRepository.GetByIdAsync(request.Id); var existingItem = await _itemRepository.GetByIdAsync(request.Id, cancellationToken);
existingItem.UpdateDetails(request.Name, request.Description, request.Price); existingItem.UpdateDetails(request.Name, request.Description, request.Price);
existingItem.UpdateBrand(request.CatalogBrandId); existingItem.UpdateBrand(request.CatalogBrandId);
@@ -50,13 +50,13 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
else else
{ {
var picName = $"{existingItem.Id}{Path.GetExtension(request.PictureName)}"; var picName = $"{existingItem.Id}{Path.GetExtension(request.PictureName)}";
if (await _webFileSystem.SavePicture($"{picName}", request.PictureBase64)) if (await _webFileSystem.SavePicture($"{picName}", request.PictureBase64, cancellationToken))
{ {
existingItem.UpdatePictureUri(picName); existingItem.UpdatePictureUri(picName);
} }
} }
await _itemRepository.UpdateAsync(existingItem); await _itemRepository.UpdateAsync(existingItem, cancellationToken);
var dto = new CatalogItemDto var dto = new CatalogItemDto
{ {

View File

@@ -33,7 +33,7 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogTypeEndpoints
{ {
var response = new ListCatalogTypesResponse(); var response = new ListCatalogTypesResponse();
var items = await _catalogTypeRepository.ListAllAsync(); var items = await _catalogTypeRepository.ListAllAsync(cancellationToken);
response.CatalogTypes.AddRange(items.Select(_mapper.Map<CatalogTypeDto>)); response.CatalogTypes.AddRange(items.Select(_mapper.Map<CatalogTypeDto>));

View File

@@ -21,7 +21,7 @@ namespace Microsoft.eShopWeb.Web.Features.MyOrders
public async Task<IEnumerable<OrderViewModel>> Handle(GetMyOrders request, CancellationToken cancellationToken) public async Task<IEnumerable<OrderViewModel>> Handle(GetMyOrders request, CancellationToken cancellationToken)
{ {
var specification = new CustomerOrdersWithItemsSpecification(request.UserName); var specification = new CustomerOrdersWithItemsSpecification(request.UserName);
var orders = await _orderRepository.ListAsync(specification); var orders = await _orderRepository.ListAsync(specification, cancellationToken);
return orders.Select(o => new OrderViewModel return orders.Select(o => new OrderViewModel
{ {

View File

@@ -19,7 +19,7 @@ namespace Microsoft.eShopWeb.Web.Features.OrderDetails
public async Task<OrderViewModel> Handle(GetOrderDetails request, CancellationToken cancellationToken) public async Task<OrderViewModel> Handle(GetOrderDetails request, CancellationToken cancellationToken)
{ {
var customerOrders = await _orderRepository.ListAsync(new CustomerOrdersWithItemsSpecification(request.UserName)); var customerOrders = await _orderRepository.ListAsync(new CustomerOrdersWithItemsSpecification(request.UserName), cancellationToken);
var order = customerOrders.FirstOrDefault(o => o.Id == request.OrderId); var order = customerOrders.FirstOrDefault(o => o.Id == request.OrderId);
if (order == null) if (order == null)

View File

@@ -23,13 +23,13 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
{ {
var basket = new Basket(_buyerId); var basket = new Basket(_buyerId);
basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>()); basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>());
_mockBasketRepo.Setup(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>())).ReturnsAsync(basket); _mockBasketRepo.Setup(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(), default)).ReturnsAsync(basket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.AddItemToBasket(basket.Id, 1, 1.50m); await basketService.AddItemToBasket(basket.Id, 1, 1.50m);
_mockBasketRepo.Verify(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>()), Times.Once); _mockBasketRepo.Verify(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(),default), Times.Once);
} }
[Fact] [Fact]
@@ -37,13 +37,13 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
{ {
var basket = new Basket(_buyerId); var basket = new Basket(_buyerId);
basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>()); basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>());
_mockBasketRepo.Setup(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>())).ReturnsAsync(basket); _mockBasketRepo.Setup(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(),default)).ReturnsAsync(basket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.AddItemToBasket(basket.Id, 1, 1.50m); await basketService.AddItemToBasket(basket.Id, 1, 1.50m);
_mockBasketRepo.Verify(x => x.UpdateAsync(basket), Times.Once); _mockBasketRepo.Verify(x => x.UpdateAsync(basket,default), Times.Once);
} }
} }
} }

View File

@@ -23,13 +23,13 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
var basket = new Basket(_buyerId); var basket = new Basket(_buyerId);
basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>()); basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>());
basket.AddItem(2, It.IsAny<decimal>(), It.IsAny<int>()); basket.AddItem(2, It.IsAny<decimal>(), It.IsAny<int>());
_mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny<int>())) _mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny<int>(),default))
.ReturnsAsync(basket); .ReturnsAsync(basket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.DeleteBasketAsync(It.IsAny<int>()); await basketService.DeleteBasketAsync(It.IsAny<int>());
_mockBasketRepo.Verify(x => x.DeleteAsync(It.IsAny<Basket>()), Times.Once); _mockBasketRepo.Verify(x => x.DeleteAsync(It.IsAny<Basket>(),default), Times.Once);
} }
} }
} }

View File

@@ -1,12 +1,9 @@
using Ardalis.Specification; using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.ApplicationCore.Services; using Microsoft.eShopWeb.ApplicationCore.Services;
using Microsoft.eShopWeb.ApplicationCore.Specifications; using Microsoft.eShopWeb.ApplicationCore.Specifications;
using Moq; using Moq;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;
@@ -46,12 +43,12 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
{ {
var anonymousBasket = null as Basket; var anonymousBasket = null as Basket;
var userBasket = new Basket(_existentUserBasketBuyerId); var userBasket = new Basket(_existentUserBasketBuyerId);
_mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>())) _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(), default))
.ReturnsAsync(anonymousBasket) .ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket); .ReturnsAsync(userBasket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId); await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>()), Times.Once); _mockBasketRepo.Verify(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(), default), Times.Once);
} }
[Fact] [Fact]
@@ -63,12 +60,12 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
var userBasket = new Basket(_existentUserBasketBuyerId); var userBasket = new Basket(_existentUserBasketBuyerId);
userBasket.AddItem(1, 10, 4); userBasket.AddItem(1, 10, 4);
userBasket.AddItem(2, 99, 3); userBasket.AddItem(2, 99, 3);
_mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>())) _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(), default))
.ReturnsAsync(anonymousBasket) .ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket); .ReturnsAsync(userBasket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId); await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.UpdateAsync(userBasket), Times.Once); _mockBasketRepo.Verify(x => x.UpdateAsync(userBasket, default), Times.Once);
Assert.Equal(3, userBasket.Items.Count); Assert.Equal(3, userBasket.Items.Count);
Assert.Contains(userBasket.Items, x => x.CatalogItemId == 1 && x.UnitPrice == 10 && x.Quantity == 5); Assert.Contains(userBasket.Items, x => x.CatalogItemId == 1 && x.UnitPrice == 10 && x.Quantity == 5);
Assert.Contains(userBasket.Items, x => x.CatalogItemId == 2 && x.UnitPrice == 99 && x.Quantity == 3); Assert.Contains(userBasket.Items, x => x.CatalogItemId == 2 && x.UnitPrice == 99 && x.Quantity == 3);
@@ -80,13 +77,13 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
{ {
var anonymousBasket = new Basket(_existentAnonymousBasketBuyerId); var anonymousBasket = new Basket(_existentAnonymousBasketBuyerId);
var userBasket = new Basket(_existentUserBasketBuyerId); var userBasket = new Basket(_existentUserBasketBuyerId);
_mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>())) _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(), default))
.ReturnsAsync(anonymousBasket) .ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket); .ReturnsAsync(userBasket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId); await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.UpdateAsync(userBasket), Times.Once); _mockBasketRepo.Verify(x => x.UpdateAsync(userBasket, default), Times.Once);
_mockBasketRepo.Verify(x => x.DeleteAsync(anonymousBasket), Times.Once); _mockBasketRepo.Verify(x => x.DeleteAsync(anonymousBasket, default), Times.Once);
} }
[Fact] [Fact]
@@ -94,12 +91,12 @@ namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTes
{ {
var anonymousBasket = new Basket(_existentAnonymousBasketBuyerId); var anonymousBasket = new Basket(_existentAnonymousBasketBuyerId);
var userBasket = null as Basket; var userBasket = null as Basket;
_mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>())) _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny<BasketWithItemsSpecification>(), default))
.ReturnsAsync(anonymousBasket) .ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket); .ReturnsAsync(userBasket);
var basketService = new BasketService(_mockBasketRepo.Object, null); var basketService = new BasketService(_mockBasketRepo.Object, null);
await basketService.TransferBasketAsync(_existentAnonymousBasketBuyerId, _nonexistentUserBasketBuyerId); await basketService.TransferBasketAsync(_existentAnonymousBasketBuyerId, _nonexistentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.AddAsync(It.Is<Basket>(x => x.BuyerId == _nonexistentUserBasketBuyerId)), Times.Once); _mockBasketRepo.Verify(x => x.AddAsync(It.Is<Basket>(x => x.BuyerId == _nonexistentUserBasketBuyerId), default), Times.Once);
} }
} }
} }

View File

@@ -21,7 +21,7 @@ namespace Microsoft.eShopWeb.UnitTests.MediatorHandlers.OrdersTests
Order order = new Order("buyerId", address, new List<OrderItem> { item }); Order order = new Order("buyerId", address, new List<OrderItem> { item });
_mockOrderRepository = new Mock<IOrderRepository>(); _mockOrderRepository = new Mock<IOrderRepository>();
_mockOrderRepository.Setup(x => x.ListAsync(It.IsAny<ISpecification<Order>>())).ReturnsAsync(new List<Order> { order }); _mockOrderRepository.Setup(x => x.ListAsync(It.IsAny<ISpecification<Order>>(),default)).ReturnsAsync(new List<Order> { order });
} }
[Fact] [Fact]

View File

@@ -21,7 +21,7 @@ namespace Microsoft.eShopWeb.UnitTests.MediatorHandlers.OrdersTests
Order order = new Order("buyerId", address, new List<OrderItem> { item }); Order order = new Order("buyerId", address, new List<OrderItem> { item });
_mockOrderRepository = new Mock<IOrderRepository>(); _mockOrderRepository = new Mock<IOrderRepository>();
_mockOrderRepository.Setup(x => x.ListAsync(It.IsAny<ISpecification<Order>>())).ReturnsAsync(new List<Order> { order }); _mockOrderRepository.Setup(x => x.ListAsync(It.IsAny<ISpecification<Order>>(),default)).ReturnsAsync(new List<Order> { order });
} }
[Fact] [Fact]