Newer
Older
BusinessRules / WarehouseProductTests.cs
@Derek Comartin Derek Comartin on 22 Aug 2023 3 KB Init
using System;
using System.Linq;
using AutoFixture;
using Shouldly;
using Xunit;

namespace EventSourcing.Demo
{
    public class WarehouseProductTests
    {
        private readonly string _sku;
        private readonly int _initialQuantity;
        private readonly WarehouseProduct _sut;
        private readonly Fixture _fixture;

        public WarehouseProductTests()
        {
            _fixture = new Fixture();
            _fixture.Customizations.Add(new Int32SequenceGenerator());
            _sku = _fixture.Create<string>();
            _initialQuantity = (int)_fixture.Create<uint>();

            _sut = WarehouseProduct.Load(_sku, new [] {
                new ProductReceived(_sku, _initialQuantity, DateTime.UtcNow)
            });
        }

        [Fact]
        public void ShipProductShouldRaiseProductShipped()
        {
            var quantityToShip = _fixture.Create<int>();
            _sut.ShipProduct(new Quantity(quantityToShip));

            var outEvents = _sut.GetUncommittedEvents();
            outEvents.Count.ShouldBe(1);
            var outEvent = outEvents.Single();
            outEvent.ShouldBeOfType<ProductShipped>();

            var productShipped = (ProductShipped)outEvent;
            productShipped.ShouldSatisfyAllConditions(
                x => x.Quantity.ShouldBe(quantityToShip),
                x => x.Sku.ShouldBe(_sku),
                x => x.EventType.ShouldBe("ProductShipped")
            );
        }

        

        [Fact]
        public void ShipProductShouldThrowIfNoQuantityOnHand()
        {
            var ex = Should.Throw<InvalidDomainException>(() => _sut.ShipProduct(new Quantity(_initialQuantity + 1)));
            ex.Message.ShouldBe("Cannot Ship to a negative Quantity on Hand.");
        }

        [Fact]
        public void ReceiveProductShouldRaiseProductReceived()
        {
            var quantityToReceive = _fixture.Create<int>();
            _sut.ReceiveProduct(new Quantity(quantityToReceive));

            var outEvents = _sut.GetUncommittedEvents();
            outEvents.Count.ShouldBe(1);
            var outEvent = outEvents.Single();
            outEvent.ShouldBeOfType<ProductReceived>();

            var productReceived = (ProductReceived)outEvent;
            productReceived.ShouldSatisfyAllConditions(
                x => x.Quantity.ShouldBe(quantityToReceive),
                x => x.Sku.ShouldBe(_sku),
                x => x.EventType.ShouldBe("ProductReceived")
            );
        }

        [Fact]
        public void AdjustInventoryShouldRaiseProductAdjusted()
        {
            var quantityToAdjust = _fixture.Create<int>();
            var reason = _fixture.Create<string>();
            _sut.AdjustInventory(new Quantity(quantityToAdjust), reason);

            var outEvents = _sut.GetUncommittedEvents();
            outEvents.Count.ShouldBe(1);
            var outEvent = outEvents.Single();
            outEvent.ShouldBeOfType<InventoryAdjusted>();

            var productShipped = (InventoryAdjusted)outEvent;
            productShipped.ShouldSatisfyAllConditions(
                x => x.Quantity.ShouldBe(quantityToAdjust),
                x => x.Sku.ShouldBe(_sku),
                x => x.Reason.ShouldBe(reason),
                x => x.EventType.ShouldBe("InventoryAdjusted")
            );
        }

        [Fact]
        public void AdjustInventoryShouldThrowIfNoQuantityOnHand()
        {
            var ex = Should.Throw<InvalidDomainException>(() => _sut.AdjustInventory(new Quantity((_initialQuantity + 1) * -1), string.Empty));
            ex.Message.ShouldBe("Cannot adjust to a negative Quantity on Hand.");
        }
        
        [Fact]
        public void ThrowInvalidQuantity()
        {
            Should.Throw<InvalidOperationException>(() => new Quantity(0));
        }
    }
}