public void SetupCalculatorTrolleyApiResult(TrolleyInfo trolleyInfo, decimal calculatedTotal) { var responseHttpContent = JsonConvert.SerializeObject(calculatedTotal); var apiUrl = "http://apihost/api/resource/trolleycalulator"; var token = "TestToken"; MockSerializer .Setup(o => o.Serialize(trolleyInfo)) .Returns <TrolleyInfo>(t => JsonConvert.SerializeObject(t)); MockExternalApiPathProvider .Setup(o => o.GetApiPath(ExternalApiPathName.CalculateTrolley)) .Returns(apiUrl); MockConfigProvider .Setup(o => o.GetConfigValue(ConfigKeys.Token)) .Returns(token); var apiRequestUrl = $"{apiUrl}?token={token}"; var jsonMimeType = "application/json"; MockMessageHandler .When(HttpMethod.Post, apiRequestUrl) .WithContent(JsonConvert.SerializeObject(trolleyInfo)) .WithHeaders("Content-Type", jsonMimeType) .Respond(jsonMimeType, responseHttpContent); }
public async Task <decimal> CalculateTrolley(TrolleyInfo trolleyInfo) { if (trolleyInfo == null) { return(0); } if (TrolleyInfoPropertiesAreNull(trolleyInfo)) { throw new ArgumentException("Products, Quantities and Specials properties cannot be null."); } string fullApiUrl = GetFullApiUrl(ExternalApiPathName.CalculateTrolley); var requestContent = new StringContent(_serializer.Serialize(trolleyInfo)); SetRequestContentHeaders(requestContent); var response = await _httpClient.PostAsync(fullApiUrl, requestContent); if (!response.IsSuccessStatusCode) { throw GetExternalApiCallException(ExternalApiPathName.CalculateTrolley, response.StatusCode); } var responseText = await response.Content.ReadAsStringAsync(); var result = Convert.ToDecimal(responseText); return(result); }
/// <summary> /// Explores the trolley info to discover the minimum possible total amount /// </summary> /// <param name="trolleyInfo"></param> /// <returns></returns> public decimal GetMinPossibleAmount(TrolleyInfo trolleyInfo) { if (trolleyInfo == null) { return(0); } if (TrolleyInfoPropertiesAreNull(trolleyInfo)) { throw new ArgumentException("Products, Quantities and Specials properties cannot be null."); } var productPriceMap = GetProductPriceMap(trolleyInfo); var shoppedProductQuantitiesMap = GetShoppedProductQuantitiesMap(trolleyInfo); var maxAmount = CalculateShoppedProductsAmountByQuantityAndPrice(shoppedProductQuantitiesMap, productPriceMap); if (maxAmount == 0) { return(0); } var applicableSpecials = GetApplicableSpecials(trolleyInfo.Specials, maxAmount, shoppedProductQuantitiesMap); if (!applicableSpecials.Any()) { return(maxAmount); } var minAmount = maxAmount; foreach (var specialList in applicableSpecials.GetPermutations(applicableSpecials.Count)) { SetMinAmountAfterApplyingSpecials(productPriceMap, shoppedProductQuantitiesMap, specialList, ref minAmount); } return(minAmount); }
public void CalculateTrolley_WhenTrolleyInfoPropertyIsNull_ReturnsZero(TrolleyInfo trolleyInfo) { // Arrange var sutFactory = new SutTrolleyCalculatorFactory(); var sutTrolleyCalculator = sutFactory.Create(); // Act Func <Task> action = async() => await sutTrolleyCalculator.CalculateTrolley(trolleyInfo); // Assert action.Should().ThrowExactlyAsync <ArgumentException>() .WithMessage("Products, Quantities and Specials properties cannot be null."); }
public async void CalculateTrolley_WhenTrolleyInfoIsValid_ReturnsTotalReceivedFromTheExternalApi() { // Arrange var trolleyInfo = new TrolleyInfo(); decimal expectedResult = 10.2m; var sutFactory = new SutTrolleyCalculatorFactory(); sutFactory.SetupCalculatorTrolleyApiResult(trolleyInfo, expectedResult); var sutTrolleyCalculator = sutFactory.Create(); // Act var result = await sutTrolleyCalculator.CalculateTrolley(trolleyInfo); // Assert result.Should().Be(expectedResult); }
private Dictionary <string, int> GetShoppedProductQuantitiesMap(TrolleyInfo trolleyInfo) { var result = new Dictionary <string, int>(); foreach (var productQuantity in trolleyInfo.Quantities) { if (result.ContainsKey(productQuantity.Name)) { result[productQuantity.Name] += productQuantity.Quantity; } else { result[productQuantity.Name] = productQuantity.Quantity; } } return(result); }
public async void CalculateTrolleyTotal_WhenInputIsValid_ReturnsCorrectResultFromService() { // Arrange var sutFactory = new SutTrolleyTotalControllerFactory(); var valueReturnedFromService = 12.3m; var trolleyInfoModel = new TrolleyInfoModel(); var trolleyInfo = new TrolleyInfo(); sutFactory.MockMapper .Setup(o => o.Map <TrolleyInfoModel, TrolleyInfo>(trolleyInfoModel)) .Returns(trolleyInfo); sutFactory.MockTrolleyCalculator .Setup(o => o.CalculateTrolley(trolleyInfo)) .Returns(Task.FromResult(valueReturnedFromService)); var sutTrolleyTotalController = sutFactory.Create(); // Act var result = await sutTrolleyTotalController.CalculateTrolleyTotal(trolleyInfoModel); // Assert result.Should().Be(valueReturnedFromService); }
public async void CalculateTrolley_WhenTrolleyInfoIsValid_ReturnsCorrectMinimumTotal(TrolleyInfo trolleyInfo, decimal expectedTotal) { // Arrange var sutTrolleyCalculator = new TrolleyCalculator2(); // Act var result = await sutTrolleyCalculator.CalculateTrolley(trolleyInfo); // Assert result.Should().Be(expectedTotal); }
private Dictionary <string, decimal> GetProductPriceMap(TrolleyInfo trolleyInfo) { return(trolleyInfo.Products.ToDictionary(q => q.Name, q => q.Price)); }
private bool TrolleyInfoPropertiesAreNull(TrolleyInfo trolleyInfo) { return(trolleyInfo.Products == null || trolleyInfo.Quantities == null || trolleyInfo.Specials == null); }
public async Task <decimal> CalculateTrolley(TrolleyInfo trolleyInfo) { return(await Task.Run(() => GetMinPossibleAmount(trolleyInfo))); }
public decimal TrolleyTotal([FromBody] TrolleyInfo trolleyInfo) { return(0.0M); }