Adding guards and more tests (#68)
* Adding single entity by spec method to repository * Adding guards and more unit tests
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Ardalis.GuardClauses" Version="1.1.1" />
|
||||||
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
23
src/ApplicationCore/Exceptions/BasketNotFoundException.cs
Normal file
23
src/ApplicationCore/Exceptions/BasketNotFoundException.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ApplicationCore.Exceptions
|
||||||
|
{
|
||||||
|
public class BasketNotFoundException : Exception
|
||||||
|
{
|
||||||
|
public BasketNotFoundException(int basketId) : base($"No basket found with id {basketId}")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BasketNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasketNotFoundException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasketNotFoundException(string message, Exception innerException) : base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/ApplicationCore/Exceptions/GuardExtensions.cs
Normal file
14
src/ApplicationCore/Exceptions/GuardExtensions.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using ApplicationCore.Exceptions;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
|
|
||||||
|
namespace Ardalis.GuardClauses
|
||||||
|
{
|
||||||
|
public static class FooGuard
|
||||||
|
{
|
||||||
|
public static void NullBasket(this IGuardClause guardClause, int basketId, Basket basket)
|
||||||
|
{
|
||||||
|
if (basket == null)
|
||||||
|
throw new BasketNotFoundException(basketId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace ApplicationCore.Interfaces
|
namespace ApplicationCore.Interfaces
|
||||||
{
|
{
|
||||||
public interface IRepository<T> where T : BaseEntity
|
public interface IRepository<T> where T : BaseEntity
|
||||||
{
|
{
|
||||||
T GetById(int id);
|
T GetById(int id);
|
||||||
|
T GetSingleBySpec(ISpecification<T> spec);
|
||||||
IEnumerable<T> ListAll();
|
IEnumerable<T> ListAll();
|
||||||
IEnumerable<T> List(ISpecification<T> spec);
|
IEnumerable<T> List(ISpecification<T> spec);
|
||||||
T Add(T entity);
|
T Add(T entity);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using ApplicationCore.Specifications;
|
using ApplicationCore.Specifications;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Ardalis.GuardClauses;
|
||||||
|
|
||||||
namespace ApplicationCore.Services
|
namespace ApplicationCore.Services
|
||||||
{
|
{
|
||||||
@@ -43,6 +44,7 @@ namespace ApplicationCore.Services
|
|||||||
|
|
||||||
public async Task<int> GetBasketItemCountAsync(string userName)
|
public async Task<int> GetBasketItemCountAsync(string userName)
|
||||||
{
|
{
|
||||||
|
Guard.Against.NullOrEmpty(userName, nameof(userName));
|
||||||
var basketSpec = new BasketWithItemsSpecification(userName);
|
var basketSpec = new BasketWithItemsSpecification(userName);
|
||||||
var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault();
|
var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault();
|
||||||
if (basket == null)
|
if (basket == null)
|
||||||
@@ -57,7 +59,9 @@ namespace ApplicationCore.Services
|
|||||||
|
|
||||||
public async Task SetQuantities(int basketId, Dictionary<string, int> quantities)
|
public async Task SetQuantities(int basketId, Dictionary<string, int> quantities)
|
||||||
{
|
{
|
||||||
|
Guard.Against.Null(quantities, nameof(quantities));
|
||||||
var basket = await _basketRepository.GetByIdAsync(basketId);
|
var basket = await _basketRepository.GetByIdAsync(basketId);
|
||||||
|
Guard.Against.NullBasket(basketId, basket);
|
||||||
foreach (var item in basket.Items)
|
foreach (var item in basket.Items)
|
||||||
{
|
{
|
||||||
if (quantities.TryGetValue(item.Id.ToString(), out var quantity))
|
if (quantities.TryGetValue(item.Id.ToString(), out var quantity))
|
||||||
@@ -71,6 +75,8 @@ namespace ApplicationCore.Services
|
|||||||
|
|
||||||
public async Task TransferBasketAsync(string anonymousId, string userName)
|
public async Task TransferBasketAsync(string anonymousId, string userName)
|
||||||
{
|
{
|
||||||
|
Guard.Against.NullOrEmpty(anonymousId, nameof(anonymousId));
|
||||||
|
Guard.Against.NullOrEmpty(userName, nameof(userName));
|
||||||
var basketSpec = new BasketWithItemsSpecification(anonymousId);
|
var basketSpec = new BasketWithItemsSpecification(anonymousId);
|
||||||
var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault();
|
var basket = (await _basketRepository.ListAsync(basketSpec)).FirstOrDefault();
|
||||||
if (basket == null) return;
|
if (basket == null) return;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using ApplicationCore.Entities.OrderAggregate;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Ardalis.GuardClauses;
|
||||||
|
|
||||||
namespace ApplicationCore.Services
|
namespace ApplicationCore.Services
|
||||||
{
|
{
|
||||||
@@ -24,6 +25,7 @@ namespace ApplicationCore.Services
|
|||||||
public async Task CreateOrderAsync(int basketId, Address shippingAddress)
|
public async Task CreateOrderAsync(int basketId, Address shippingAddress)
|
||||||
{
|
{
|
||||||
var basket = await _basketRepository.GetByIdAsync(basketId);
|
var basket = await _basketRepository.GetByIdAsync(basketId);
|
||||||
|
Guard.Against.NullBasket(basketId, basket);
|
||||||
var items = new List<OrderItem>();
|
var items = new List<OrderItem>();
|
||||||
foreach (var item in basket.Items)
|
foreach (var item in basket.Items)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ namespace Infrastructure.Data
|
|||||||
return _dbContext.Set<T>().Find(id);
|
return _dbContext.Set<T>().Find(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T GetSingleBySpec(ISpecification<T> spec)
|
||||||
|
{
|
||||||
|
return List(spec).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual async Task<T> GetByIdAsync(int id)
|
public virtual async Task<T> GetByIdAsync(int id)
|
||||||
{
|
{
|
||||||
return await _dbContext.Set<T>().FindAsync(id);
|
return await _dbContext.Set<T>().FindAsync(id);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Infrastructure.Logging
|
|||||||
{
|
{
|
||||||
_logger.LogWarning(message, args);
|
_logger.LogWarning(message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogInformation(string message, params object[] args)
|
public void LogInformation(string message, params object[] args)
|
||||||
{
|
{
|
||||||
_logger.LogInformation(message, args);
|
_logger.LogInformation(message, args);
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using ApplicationCore.Exceptions;
|
||||||
|
using ApplicationCore.Interfaces;
|
||||||
|
using ApplicationCore.Services;
|
||||||
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace UnitTests.ApplicationCore.Services.BasketServiceTests
|
||||||
|
{
|
||||||
|
public class SetQuantities
|
||||||
|
{
|
||||||
|
private int _invalidId = -1;
|
||||||
|
private Mock<IAsyncRepository<Basket>> _mockBasketRepo;
|
||||||
|
|
||||||
|
public SetQuantities()
|
||||||
|
{
|
||||||
|
_mockBasketRepo = new Mock<IAsyncRepository<Basket>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ThrowsGivenInvalidBasketId()
|
||||||
|
{
|
||||||
|
var basketService = new BasketService(_mockBasketRepo.Object, null, null, null);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<BasketNotFoundException>(async () =>
|
||||||
|
await basketService.SetQuantities(_invalidId, new System.Collections.Generic.Dictionary<string, int>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ThrowsGivenNullQuantities()
|
||||||
|
{
|
||||||
|
var basketService = new BasketService(null, null, null, null);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
|
||||||
|
await basketService.SetQuantities(123, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using ApplicationCore.Services;
|
||||||
|
using System;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace UnitTests.ApplicationCore.Services.BasketServiceTests
|
||||||
|
{
|
||||||
|
public class TransferBasket
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async void ThrowsGivenNullAnonymousId()
|
||||||
|
{
|
||||||
|
var basketService = new BasketService(null, null, null, null);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(async () => await basketService.TransferBasketAsync(null, "steve"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ThrowsGivenNullUserId()
|
||||||
|
{
|
||||||
|
var basketService = new BasketService(null, null, null, null);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<ArgumentNullException>(async () => await basketService.TransferBasketAsync("abcdefg", null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user