Skip to content

Commit

Permalink
Remove basket items when basket is deleted (dotnet-architecture#170)
Browse files Browse the repository at this point in the history
* Proving out removing the basket items at the same time the basket is deleted

* Fixing existing unit tests

* Adding a unit test for the Deletebasket method

* Rename test and deleting basket items before basket

* Added integration test for DeleteAsync method for BasketItems

- Also added a BasketBuilder to create a Basket with no items, or one item.
  • Loading branch information
efleming18 authored and ardalis committed Dec 28, 2018
1 parent 9528559 commit eb02750
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 5 deletions.
10 changes: 9 additions & 1 deletion src/ApplicationCore/Services/BasketService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ namespace Microsoft.eShopWeb.ApplicationCore.Services
public class BasketService : IBasketService
{
private readonly IAsyncRepository<Basket> _basketRepository;
private readonly IAsyncRepository<BasketItem> _basketItemRepository;
private readonly IUriComposer _uriComposer;
private readonly IAppLogger<BasketService> _logger;
private readonly IRepository<CatalogItem> _itemRepository;

public BasketService(IAsyncRepository<Basket> basketRepository,
IRepository<CatalogItem> itemRepository,
IUriComposer uriComposer,
IAppLogger<BasketService> logger)
IAppLogger<BasketService> logger,
IAsyncRepository<BasketItem> basketItemRepository)
{
_basketRepository = basketRepository;
_uriComposer = uriComposer;
_logger = logger;
_itemRepository = itemRepository;
_basketItemRepository = basketItemRepository;
}

public async Task AddItemToBasket(int basketId, int catalogItemId, decimal price, int quantity)
Expand All @@ -40,6 +43,11 @@ public async Task DeleteBasketAsync(int basketId)
{
var basket = await _basketRepository.GetByIdAsync(basketId);

foreach (var item in basket.Items)
{
await _basketItemRepository.DeleteAsync(item);
}

await _basketRepository.DeleteAsync(basket);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
using Microsoft.eShopWeb.Infrastructure.Data;
using Microsoft.eShopWeb.UnitTests.Builders;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.eShopWeb.IntegrationTests.Repositories.BasketItemRepositoryTests
{
public class DeleteAsync_Should
{
private readonly CatalogContext _catalogContext;
private readonly EfRepository<Basket> _basketRepository;
private readonly EfRepository<BasketItem> _basketItemRepository;
private BasketBuilder BasketBuilder { get; } = new BasketBuilder();
private readonly ITestOutputHelper _output;

public DeleteAsync_Should(ITestOutputHelper output)
{
_output = output;
var dbOptions = new DbContextOptionsBuilder<CatalogContext>()
.UseInMemoryDatabase(databaseName: "TestCatalog")
.Options;
_catalogContext = new CatalogContext(dbOptions);
_basketRepository = new EfRepository<Basket>(_catalogContext);
_basketItemRepository = new EfRepository<BasketItem>(_catalogContext);
}

[Fact]
public async Task DeleteItemFromBasket()
{
var existingBasket = BasketBuilder.WithOneBasketItem();
_catalogContext.Add(existingBasket);
_catalogContext.SaveChanges();

await _basketItemRepository.DeleteAsync(existingBasket.Items.FirstOrDefault());
_catalogContext.SaveChanges();

var basketFromDB = _basketRepository.GetById(BasketBuilder.BasketId);

Assert.Equal(0, basketFromDB.Items.Count);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.ApplicationCore.Services;
using Moq;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTests
{
public class DeleteBasket
{
private Mock<IAsyncRepository<Basket>> _mockBasketRepo;
private Mock<IAsyncRepository<BasketItem>> _mockBasketItemRepo;

public DeleteBasket()
{
_mockBasketRepo = new Mock<IAsyncRepository<Basket>>();
_mockBasketItemRepo = new Mock<IAsyncRepository<BasketItem>>();
}

[Fact]
public async Task Should_InvokeBasketRepoOnceAndBasketItemRepoTwice_Given_TwoItemsInBasket()
{
var basket = new Basket();
basket.AddItem(1, It.IsAny<decimal>(), It.IsAny<int>());
basket.AddItem(2, It.IsAny<decimal>(), It.IsAny<int>());
_mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny<int>()))
.ReturnsAsync(basket);
var basketService = new BasketService(_mockBasketRepo.Object, null, null, null, _mockBasketItemRepo.Object);

await basketService.DeleteBasketAsync(It.IsAny<int>());

_mockBasketRepo.Verify(x => x.DeleteAsync(It.IsAny<Basket>()), Times.Once);
_mockBasketItemRepo.Verify(x => x.DeleteAsync(It.IsAny<BasketItem>()), Times.Exactly(2));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public SetQuantities()
[Fact]
public async void ThrowsGivenInvalidBasketId()
{
var basketService = new BasketService(_mockBasketRepo.Object, null, null, null);
var basketService = new BasketService(_mockBasketRepo.Object, null, null, null, null);

await Assert.ThrowsAsync<BasketNotFoundException>(async () =>
await basketService.SetQuantities(_invalidId, new System.Collections.Generic.Dictionary<string, int>()));
Expand All @@ -30,7 +30,7 @@ await Assert.ThrowsAsync<BasketNotFoundException>(async () =>
[Fact]
public async void ThrowsGivenNullQuantities()
{
var basketService = new BasketService(null, null, null, null);
var basketService = new BasketService(null, null, null, null, null);

await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await basketService.SetQuantities(123, null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ public class TransferBasket
[Fact]
public async void ThrowsGivenNullAnonymousId()
{
var basketService = new BasketService(null, null, null, null);
var basketService = new BasketService(null, 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);
var basketService = new BasketService(null, null, null, null, null);

await Assert.ThrowsAsync<ArgumentNullException>(async () => await basketService.TransferBasketAsync("abcdefg", null));
}
Expand Down
34 changes: 34 additions & 0 deletions tests/UnitTests/Builders/BasketBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;

namespace Microsoft.eShopWeb.UnitTests.Builders
{
public class BasketBuilder
{
private Basket _basket;
public string BasketBuyerId => "testbuyerId@test.com";
public int BasketId => 1;

public BasketBuilder()
{
_basket = WithNoItems();
}

public Basket Build()
{
return _basket;
}

public Basket WithNoItems()
{
_basket = new Basket { BuyerId = BasketBuyerId, Id = BasketId };
return _basket;
}

public Basket WithOneBasketItem()
{
_basket = new Basket { BuyerId = BasketBuyerId, Id = BasketId };
_basket.AddItem(2, 3.40m, 4);
return _basket;
}
}
}

0 comments on commit eb02750

Please sign in to comment.