ex-int-04-shipping-cost/ShippingCosts.Test/LPSShippingCostCalculatorTests.cs
github-classroom[bot] 5db225db88
Initial commit
2025-04-29 15:01:53 +00:00

231 lines
9.3 KiB
C#

using ShippingCosts.Contracts;
using ShippingCosts.Implementations;
namespace ShippingCosts.Test;
public sealed class LPSShippingCostCalculatorTests : ShippingCostCalculatorBaseTestBase
{
private readonly ICountryDistanceProvider _defaultDistanceProvider = ConfigureDefaultCountryProvider();
private readonly IMeasuredBox _sampleBox = ConfigureDefaultBox();
[Fact]
public void CarrierName()
{
new LPSShippingCostCalculator(_defaultDistanceProvider).CarrierName.Should()
.NotBeNullOrWhiteSpace()
.And.Be("Leonding Parcel Service");
}
[Fact]
public void CalculateShippingCosts_ValidCountry()
{
var calculator = new LPSShippingCostCalculator(_defaultDistanceProvider);
calculator.CalculateShippingCosts(CountryNotNeighborEu, _sampleBox)
.Should().NotBeNull("country is known, shipping price can be calculated");
}
[Fact]
public void CalculateShippingCosts_InvalidCountry()
{
var calculator = new LPSShippingCostCalculator(_defaultDistanceProvider);
calculator.CalculateShippingCosts("Atlantis", _sampleBox)
.Should().BeNull("country is not known, shipping price cannot be calculated");
}
[Theory]
[MemberData(nameof(CalculateShippingCostsWeightData))]
public void CalculateShippingCosts_Weight(double weight, decimal? expectedPrice)
{
var distanceProvider = Substitute.For<ICountryDistanceProvider>();
distanceProvider.IsPossibleCountry(Arg.Any<string>()).ReturnsForAnyArgs(true);
distanceProvider.GetDistanceTo(Arg.Any<string>())
.ReturnsForAnyArgs(new CountryDistanceInformation(0, true, true));
var minSizeBox = Substitute.For<IMeasuredBox>();
minSizeBox.Width.Returns(1);
minSizeBox.Height.Returns(1);
minSizeBox.Depth.Returns(1);
minSizeBox.Weight.Returns(weight);
var calculator = new LPSShippingCostCalculator(distanceProvider);
calculator.CalculateShippingCosts(string.Empty, minSizeBox)
.Should().Be(expectedPrice + BasePriceDistance, "weight cost + base price distance");
}
[Theory]
[MemberData(nameof(CalculateShippingCostsSizeData))]
public void CalculateShippingCosts_Size(int boxSize, decimal? expectedPrice)
{
var distanceProvider = Substitute.For<ICountryDistanceProvider>();
distanceProvider.IsPossibleCountry(Arg.Any<string>()).ReturnsForAnyArgs(true);
distanceProvider.GetDistanceTo(Arg.Any<string>())
.ReturnsForAnyArgs(new CountryDistanceInformation(0, true, true));
var minWeightBox = Substitute.For<IMeasuredBox>();
minWeightBox.Width.Returns(1);
minWeightBox.Height.Returns(1);
minWeightBox.Depth.Returns(boxSize - 1); // size sum will be longest + shortest => 1 + (boxSize - 1) = boxSize
minWeightBox.Weight.Returns(0.1D);
var calculator = new LPSShippingCostCalculator(distanceProvider);
calculator.CalculateShippingCosts(string.Empty, minWeightBox)
.Should().Be(expectedPrice + BasePriceDistance, "size cost + base price distance");
}
[Theory]
[MemberData(nameof(CalculateShippingCostsDistanceData))]
public void CalculateShippingCosts_Distance(CountryDistanceInformation distance, decimal expectedPrice)
{
var distanceProvider = Substitute.For<ICountryDistanceProvider>();
distanceProvider.IsPossibleCountry(Arg.Any<string>()).ReturnsForAnyArgs(true);
distanceProvider.GetDistanceTo(Arg.Any<string>()).ReturnsForAnyArgs(distance);
var minimalBox = Substitute.For<IMeasuredBox>();
minimalBox.Width.Returns(1);
minimalBox.Height.Returns(1);
minimalBox.Depth.Returns(1);
minimalBox.Weight.Returns(0.1D);
var calculator = new LPSShippingCostCalculator(distanceProvider);
calculator.CalculateShippingCosts(string.Empty, minimalBox)
.Should().Be(expectedPrice + BasePriceDistance, "distance cost + base price distance");
}
[Theory]
[MemberData(nameof(CalculateShippingCostsData))]
public void CalculateShippingCosts(CountryDistanceInformation distance, IMeasuredBox box, decimal expectedPrice)
{
var distanceProvider = Substitute.For<ICountryDistanceProvider>();
distanceProvider.IsPossibleCountry(Arg.Any<string>()).ReturnsForAnyArgs(true);
distanceProvider.GetDistanceTo(Arg.Any<string>()).ReturnsForAnyArgs(distance);
var calculator = new LPSShippingCostCalculator(distanceProvider);
calculator.CalculateShippingCosts(string.Empty, box)
.Should().Be(expectedPrice);
}
[Fact]
public void InterfaceAndClassHierarchy()
{
var calculator = new LPSShippingCostCalculator(_defaultDistanceProvider);
calculator.Should().BeAssignableTo<ShippingCostCalculatorBase>()
.And.BeAssignableTo<IShippingCostCalculator>();
}
#region Test Data
private const string CountryNeighborEu = "A";
private const string CountryNeighborNotEu = "B";
private const string CountryNotNeighborEu = "C";
private const string CountryNotNeighborNotEu = "D";
private const decimal BasePriceDistance = 2.99M;
public static TheoryData<double, decimal?> CalculateShippingCostsWeightData() =>
new()
{
{ 0.4D, 0M },
{ 1.1D, 0M },
{ 1.49D, 0M },
{ 1.5D, 0.5M },
{ 1.85D, 0.5M },
{ 2.8D, 1.5M },
{ 3D, 1.65M },
{ 4.22D, 2.321M },
{ 34.9D, 19.195M },
{ 38D, 20M },
{ 51.3D, 20M },
{ -2D, null },
{ 0, null }
};
public static TheoryData<int, decimal?> CalculateShippingCostsSizeData() =>
new()
{
{ 40, 0M },
{ 120, 0M },
{ 249, 0M },
{ 250, 0.75M },
{ 399, 0.75M },
{ 400, 1.25M },
{ 581, 1.25M },
{ 677, 2.6M },
{ 901, 3.5M },
{ 1492, 3.5M },
{ -1, null },
{ 0, null }
};
public static TheoryData<CountryDistanceInformation, decimal> CalculateShippingCostsDistanceData() =>
new()
{
{ new CountryDistanceInformation(200, true, false), 3.315M },
{ new CountryDistanceInformation(415, true, true), 0.825M },
{ new CountryDistanceInformation(857, false, true), 2.2M },
{ new CountryDistanceInformation(1549, false, false), 6.89M },
{ new CountryDistanceInformation(2087, true, false), 6.615M },
{ new CountryDistanceInformation(2796, true, true), 4.95M },
{ new CountryDistanceInformation(3448, false, true), 7.7M },
{ new CountryDistanceInformation(4179, false, false), 12.39M },
{ new CountryDistanceInformation(5028, true, false), 11.565M },
{ new CountryDistanceInformation(5886, true, true), 9.9M },
{ new CountryDistanceInformation(6632, false, true), 15.4M },
{ new CountryDistanceInformation(7356, false, false), 18.99M },
{ new CountryDistanceInformation(8223, true, false), 16.515M },
{ new CountryDistanceInformation(9010, true, true), 15.675M },
{ new CountryDistanceInformation(9671, false, true), 22M },
{ new CountryDistanceInformation(10463, false, false), 25.59M }
};
public static TheoryData<CountryDistanceInformation, IMeasuredBox, decimal> CalculateShippingCostsData() =>
new()
{
{
new CountryDistanceInformation(857, false, true),
CreateBox(400, 360, 220, 3.2D),
8.2M
},
{
new CountryDistanceInformation(2087, true, false),
CreateBox(190, 80, 100, 1.45D),
10.355M
},
{
new CountryDistanceInformation(386, true, true),
ConfigureDefaultBox(),
5.065M
},
{
new CountryDistanceInformation(7356, false, false),
CreateBox(811, 490, 550, 176.2D),
45.48M
}
};
private static IMeasuredBox ConfigureDefaultBox() => CreateBox(320, 160, 200, 0.8D);
private static ICountryDistanceProvider ConfigureDefaultCountryProvider()
{
var provider = Substitute.For<ICountryDistanceProvider>();
provider.IsPossibleCountry(Arg.Is<string>(n => new[]
{
CountryNeighborEu, CountryNeighborNotEu, CountryNotNeighborEu, CountryNotNeighborNotEu
}.Contains(n)))
.Returns(true);
provider.GetDistanceTo(Arg.Is(CountryNeighborEu))
.Returns(new CountryDistanceInformation(640, true, true));
provider.GetDistanceTo(Arg.Is(CountryNeighborNotEu))
.Returns(new CountryDistanceInformation(480, true, false));
provider.GetDistanceTo(Arg.Is(CountryNotNeighborEu))
.Returns(new CountryDistanceInformation(1311, false, true));
provider.GetDistanceTo(Arg.Is(CountryNotNeighborNotEu))
.Returns(new CountryDistanceInformation(6874, false, false));
return provider;
}
#endregion
}