public void CalculateProviderResult_WhenAllocationModelThrowsException_ShouldThrowException() { // Arrange CalculationEngine calcEngine = CreateCalculationEngine(); IAllocationModel mockAllocationModel = Substitute.For <IAllocationModel>(); mockAllocationModel .Execute(Arg.Any <List <ProviderSourceDataset> >(), Arg.Any <ProviderSummary>()) .Throws(new DivideByZeroException()); List <CalculationSummaryModel> models = new List <CalculationSummaryModel> { new CalculationSummaryModel() { CalculationType = CalculationType.Number, Name = "Test", Id = "Test" } }; ProviderSummary provider = new ProviderSummary(); List <ProviderSourceDataset> sourceDataset = new List <ProviderSourceDataset>(); // Act Action calculateProviderResultMethod = () => { calcEngine.CalculateProviderResults(mockAllocationModel, CreateBuildProject(), models, provider, sourceDataset); }; // Assert calculateProviderResultMethod .Should() .ThrowExactly <DivideByZeroException>(); }
public async Task <(IEnumerable <CalculationResult>, long)> Execute(string specificationId, string providerId) { AllocationFactory allocationFactory = new AllocationFactory(_logger, _featureToggles); IAllocationModel allocationModel = allocationFactory.CreateAllocationModel(typeof(Calculations).Assembly); IEnumerable <Models.Results.ProviderSourceDataset> providerSourceDatasetsResult = await _providerSourceDatasetsRepository.GetProviderSourceDatasetsByProviderIdsAndSpecificationId(new string[] { providerId }, specificationId); List <ProviderSourceDataset> providerSourceDatasets = new List <ProviderSourceDataset>(providerSourceDatasetsResult); IEnumerable <ProviderSummary> providers = await _providerService.FetchCoreProviderData(); ProviderSummary provider = providers.FirstOrDefault(p => p.Id == providerId); if (provider == null) { throw new InvalidOperationException("Provider not found"); } Stopwatch sw = Stopwatch.StartNew(); IEnumerable <CalculationResult> calculationResults = allocationModel.Execute(providerSourceDatasets, provider, null); sw.Stop(); return(calculationResults, sw.ElapsedMilliseconds); }
public void CalculateProviderResult_WhenCalculationsAreNull_ShouldReturnResultWithEmptyCalculations() { // Arrange IAllocationModel mockAllocationModel = Substitute.For <IAllocationModel>(); mockAllocationModel .Execute( Arg.Any <Dictionary <string, ProviderSourceDataset> >(), Arg.Any <ProviderSummary>(), Arg.Any <IEnumerable <CalculationAggregation> >()) .Returns(new CalculationResultContainer { FundingLineResults = new List <FundingLineResult>() }); CalculationEngine calculationEngine = CreateCalculationEngine(); ProviderSummary providerSummary = CreateDummyProviderSummary(); BuildProject buildProject = CreateBuildProject(); // Act ProviderResult result = calculationEngine.CalculateProviderResults( mockAllocationModel, buildProject.SpecificationId, null, providerSummary, new Dictionary <string, ProviderSourceDataset>()); // Assert result.CalculationResults.Should().BeNull(); result.Provider.Should().Be(providerSummary); result.SpecificationId.Should().BeEquivalentTo(buildProject.SpecificationId); result.Id.Should().BeEquivalentTo(GenerateId(providerSummary.Id, buildProject.SpecificationId)); }
async public Task GenerateAllocations_GivenBuildProject_Runs() { //Arrange BuildProject buildProject = CreateBuildProject(); buildProject.Build.Assembly = MockData.GetMockAssembly(); IEnumerable <ProviderSummary> providers = new[] { new ProviderSummary { Id = ProviderId, Name = ProviderName } }; IEnumerable <ProviderSourceDataset> datasets = new[] { new ProviderSourceDataset() }; Func <string, string, Task <IEnumerable <ProviderSourceDataset> > > func = (s, p) => { return(Task.FromResult(datasets)); }; IEnumerable <CalculationResult> calculationResults = new[] { new CalculationResult { Calculation = new Reference { Id = CalculationId }, } }; IAllocationModel allocationModel = Substitute.For <IAllocationModel>(); allocationModel .Execute(Arg.Any <List <ProviderSourceDataset> >(), Arg.Any <ProviderSummary>()) .Returns(calculationResults); IAllocationFactory allocationFactory = Substitute.For <IAllocationFactory>(); allocationFactory .CreateAllocationModel(Arg.Any <Assembly>()) .Returns(allocationModel); ILogger logger = CreateLogger(); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); List <CalculationSummaryModel> calculations = new List <CalculationSummaryModel>() { new CalculationSummaryModel() { Id = CalculationId, }, new CalculationSummaryModel() { Id = "calc2", }, new CalculationSummaryModel() { Id = "calc3", } }; calculationsRepository .GetCalculationSummariesForSpecification(Arg.Any <string>()) .Returns(calculations); CalculationEngine calculationEngine = CreateCalculationEngine(allocationFactory, calculationsRepository, logger: logger); //Act IEnumerable <ProviderResult> results = await calculationEngine.GenerateAllocations(buildProject, providers, func); //Assert results .Count() .Should() .Be(1); results .First() .CalculationResults .Count .Should() .Be(3); }
public void CalculateProviderResult_WhenCalculationValuesReturnedWithMultipleAllocationLinesAndMixOfValuesAndNulls_ThenAllocationLineValuesAreSetCorrectly() { // Arrange List <Reference> policySpecificationsForFundingCalc = new List <Reference>() { new Reference("Spec1", "SpecOne"), new Reference("Spec2", "SpecTwo") }; List <Reference> policySpecificationsForNumberCalc = new List <Reference>() { new Reference("Spec1", "SpecOne"), }; Reference allocationLine1 = new Reference("allocationLine", "allocation line for Funding Calc and number calc"); Reference allocationLine2 = new Reference("allocationLine2", "Second allocation line"); Reference allocationLine3 = new Reference("allocationLine3", "Allocation line excluded"); CalculationResult calc1 = new CalculationResult() { CalculationType = CalculationType.Funding, Calculation = new Reference("calc1", "Calc 1"), AllocationLine = allocationLine1, CalculationSpecification = new Reference("FSpect", "FundingSpecification"), PolicySpecifications = policySpecificationsForFundingCalc, Value = 10000 }; CalculationResult calc2 = new CalculationResult() { CalculationType = CalculationType.Funding, Calculation = new Reference("calc2", "Calc 2"), AllocationLine = allocationLine1, CalculationSpecification = new Reference("FSpec2", "FundingSpecification2"), PolicySpecifications = policySpecificationsForNumberCalc, Value = 20000 }; CalculationResult calc3 = new CalculationResult() { CalculationType = CalculationType.Funding, Calculation = new Reference("calc3", "Calc 3"), AllocationLine = allocationLine2, CalculationSpecification = new Reference("calc3", "Calc 3"), PolicySpecifications = policySpecificationsForNumberCalc, Value = 67 }; CalculationResult calc4 = new CalculationResult() { CalculationType = CalculationType.Funding, Calculation = new Reference("calc4", "Calc 4"), AllocationLine = allocationLine3, CalculationSpecification = new Reference("calc4", "Calc 4"), PolicySpecifications = policySpecificationsForNumberCalc, Value = null, }; List <CalculationResult> calculationResults = new List <CalculationResult>() { calc1, calc2, calc3, calc4, }; IAllocationModel mockAllocationModel = Substitute.For <IAllocationModel>(); mockAllocationModel .Execute(Arg.Any <List <ProviderSourceDataset> >(), Arg.Any <ProviderSummary>()) .Returns(calculationResults); CalculationEngine calculationEngine = CreateCalculationEngine(); ProviderSummary providerSummary = CreateDummyProviderSummary(); BuildProject buildProject = CreateBuildProject(); IEnumerable <CalculationSummaryModel> calculationSummaryModels = new[] { new CalculationSummaryModel() { Id = "calc1", Name = "Calc 1", CalculationType = CalculationType.Funding }, new CalculationSummaryModel() { Id = "calc2", Name = "Calc 2", CalculationType = CalculationType.Funding }, new CalculationSummaryModel() { Id = "calc3", Name = "Calc 3", CalculationType = CalculationType.Funding }, new CalculationSummaryModel() { Id = "calc4", Name = "Calc 4", CalculationType = CalculationType.Funding }, }; // Act var calculateProviderResults = calculationEngine.CalculateProviderResults(mockAllocationModel, buildProject, calculationSummaryModels, providerSummary, new List <ProviderSourceDataset>()); ProviderResult result = calculateProviderResults; // Assert result .AllocationLineResults .Should() .HaveCount(3); // Values are summed for allocation line result .AllocationLineResults[0] .Value .Should() .Be(30000); result .AllocationLineResults[1] .Value .Should() .Be(67); // All calculations for Allocation Line 3 returned nulls - therefore allocation line value is null result .AllocationLineResults[2] .Value .Should() .Be(null); }
public void CalculateProviderResult_WhenCalculationsAreNotEmpty_ShouldReturnCorrectResult() { // Arrange List <Reference> policySpecificationsForFundingCalc = new List <Reference>() { new Reference("Spec1", "SpecOne"), new Reference("Spec2", "SpecTwo") }; List <Reference> policySpecificationsForNumberCalc = new List <Reference>() { new Reference("Spec1", "SpecOne"), }; Reference allocationLineReturned = new Reference("allocationLine", "allocation line for Funding Calc and number calc"); Reference fundingCalcReference = new Reference("CalcF1", "Funding calc 1"); Reference fundingCalcSpecificationReference = new Reference("FSpect", "FundingSpecification"); Reference numbercalcReference = new Reference("CalcF2", "Funding calc 2"); Reference numbercalcSpecificationReference = new Reference("FSpec2", "FundingSpecification2"); CalculationResult fundingCalcReturned = new CalculationResult() { CalculationType = CalculationType.Funding, Calculation = fundingCalcReference, AllocationLine = allocationLineReturned, CalculationSpecification = fundingCalcSpecificationReference, PolicySpecifications = policySpecificationsForFundingCalc, Value = 10000 }; CalculationResult fundingCalcReturned2 = new CalculationResult() { CalculationType = CalculationType.Funding, Calculation = numbercalcReference, AllocationLine = allocationLineReturned, CalculationSpecification = numbercalcSpecificationReference, PolicySpecifications = policySpecificationsForNumberCalc, Value = 20000 }; List <CalculationResult> calculationResults = new List <CalculationResult>() { fundingCalcReturned, fundingCalcReturned2 }; IAllocationModel mockAllocationModel = Substitute.For <IAllocationModel>(); mockAllocationModel .Execute(Arg.Any <List <ProviderSourceDataset> >(), Arg.Any <ProviderSummary>()) .Returns(calculationResults); CalculationEngine calculationEngine = CreateCalculationEngine(); ProviderSummary providerSummary = CreateDummyProviderSummary(); BuildProject buildProject = CreateBuildProject(); var nonMatchingCalculationModel = new CalculationSummaryModel() { Id = "Non matching calculation", Name = "Non matching calculation", CalculationType = CalculationType.Funding }; IEnumerable <CalculationSummaryModel> calculationSummaryModels = new[] { new CalculationSummaryModel() { Id = fundingCalcReference.Id, Name = fundingCalcReference.Name, CalculationType = CalculationType.Funding }, new CalculationSummaryModel() { Id = numbercalcReference.Id, Name = numbercalcReference.Name, CalculationType = CalculationType.Funding }, nonMatchingCalculationModel }; // Act var calculateProviderResults = calculationEngine.CalculateProviderResults(mockAllocationModel, buildProject, calculationSummaryModels, providerSummary, new List <ProviderSourceDataset>()); ProviderResult result = calculateProviderResults; // Assert result.Provider.Should().Be(providerSummary); result.SpecificationId.Should().BeEquivalentTo(buildProject.SpecificationId); result.Id.Should().BeEquivalentTo(GenerateId(providerSummary.Id, buildProject.SpecificationId)); result.CalculationResults.Should().HaveCount(3); result.AllocationLineResults.Should().HaveCount(1); AllocationLineResult allocationLine = result.AllocationLineResults[0]; allocationLine.Value = 30000; CalculationResult fundingCalcResult = result.CalculationResults.First(cr => cr.Calculation.Id == fundingCalcReference.Id); fundingCalcResult.Calculation.Should().BeEquivalentTo(fundingCalcReference); fundingCalcResult.CalculationType.Should().BeEquivalentTo(fundingCalcReturned.CalculationType); fundingCalcResult.AllocationLine.Should().BeEquivalentTo(allocationLineReturned); fundingCalcResult.CalculationSpecification.Should().BeEquivalentTo(fundingCalcSpecificationReference); fundingCalcResult.PolicySpecifications.Should().BeEquivalentTo(policySpecificationsForFundingCalc); fundingCalcResult.Value.Should().Be(fundingCalcReturned.Value.Value); CalculationResult numberCalcResult = result.CalculationResults.First(cr => cr.Calculation.Id == numbercalcReference.Id); numberCalcResult.Calculation.Should().BeEquivalentTo(numbercalcReference); numberCalcResult.CalculationType.Should().BeEquivalentTo(fundingCalcReturned2.CalculationType); numberCalcResult.AllocationLine.Should().BeEquivalentTo(allocationLineReturned); numberCalcResult.CalculationSpecification.Should().BeEquivalentTo(numbercalcSpecificationReference); numberCalcResult.PolicySpecifications.Should().BeEquivalentTo(policySpecificationsForNumberCalc); numberCalcResult.Value.Should().Be(fundingCalcReturned2.Value.Value); CalculationResult nonMatchingCalcResult = result.CalculationResults.First(cr => cr.Calculation.Id == "Non matching calculation"); nonMatchingCalcResult.Calculation.Should().BeEquivalentTo(new Reference(nonMatchingCalculationModel.Id, nonMatchingCalculationModel.Name)); nonMatchingCalcResult.CalculationType.Should().BeEquivalentTo(nonMatchingCalculationModel.CalculationType); nonMatchingCalcResult.AllocationLine.Should().BeNull(); nonMatchingCalcResult.CalculationSpecification.Should().BeNull(); nonMatchingCalcResult.PolicySpecifications.Should().BeNull(); nonMatchingCalcResult.Value.Should().BeNull(); }
public ProviderResult CalculateProviderResults(IAllocationModel model, BuildProject buildProject, IEnumerable <CalculationSummaryModel> calculations, ProviderSummary provider, IEnumerable <ProviderSourceDataset> providerSourceDatasets, IEnumerable <CalculationAggregation> aggregations = null) { var stopwatch = new Stopwatch(); stopwatch.Start(); IEnumerable <CalculationResult> calculationResults = model.Execute(providerSourceDatasets != null ? providerSourceDatasets.ToList() : new List <ProviderSourceDataset>(), provider, aggregations).ToArray(); var providerCalResults = calculationResults.ToDictionary(x => x.Calculation?.Id); stopwatch.Stop(); if (providerCalResults.Count > 0) { _logger.Debug($"{providerCalResults.Count} calcs in {stopwatch.ElapsedMilliseconds}ms ({stopwatch.ElapsedMilliseconds / providerCalResults.Count: 0.0000}ms)"); } else { _logger.Information("There are no calculations to executed for specification ID {specificationId}", buildProject.SpecificationId); } ProviderResult providerResult = new ProviderResult { Provider = provider, SpecificationId = buildProject.SpecificationId }; byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes($"{providerResult.Provider.Id}-{providerResult.SpecificationId}"); providerResult.Id = Convert.ToBase64String(plainTextBytes); List <CalculationResult> results = new List <CalculationResult>(); if (calculations != null) { foreach (CalculationSummaryModel calculation in calculations) { CalculationResult result = new CalculationResult { Calculation = calculation.GetReference(), CalculationType = calculation.CalculationType, Version = calculation.Version }; if (providerCalResults.TryGetValue(calculation.Id, out CalculationResult calculationResult)) { result.CalculationSpecification = calculationResult.CalculationSpecification; if (calculationResult.AllocationLine != null) { result.AllocationLine = calculationResult.AllocationLine; } result.PolicySpecifications = calculationResult.PolicySpecifications; // The default for the calculation is to return Decimal.MinValue - if this is the case, then subsitute a 0 value as the result, instead of the negative number. if (calculationResult.Value != decimal.MinValue) { result.Value = calculationResult.Value; } else { result.Value = 0; } result.ExceptionType = calculationResult.ExceptionType; result.ExceptionMessage = calculationResult.ExceptionMessage; } results.Add(result); } } providerResult.CalculationResults = results.ToList(); providerResult.AllocationLineResults = results.Where(x => x.CalculationType == CalculationType.Funding && x.AllocationLine != null) .GroupBy(x => x.AllocationLine).Select(x => new AllocationLineResult { AllocationLine = x.Key, Value = x.All(v => !v.Value.HasValue) ? (decimal?)null : x.Sum(v => v.Value ?? decimal.Zero) }).ToList(); return(providerResult); }
public ProviderResult CalculateProviderResults( IAllocationModel model, string specificationId, IEnumerable <CalculationSummaryModel> calculations, ProviderSummary provider, IDictionary <string, ProviderSourceDataset> providerSourceDatasets, IEnumerable <CalculationAggregation> aggregations = null) { var stopwatch = new Stopwatch(); stopwatch.Start(); CalculationResultContainer calculationResultContainer = model.Execute(providerSourceDatasets, provider, aggregations); IEnumerable <CalculationResult> calculationResultItems = calculationResultContainer.CalculationResults; stopwatch.Stop(); IDictionary <string, double> metrics = new Dictionary <string, double>() { { "calculation-provider-calcsMs", stopwatch.ElapsedMilliseconds }, { "calculation-provider-calcsTotal", calculations.AnyWithNullCheck() ? calculations.Count() : 0 }, { "calculation-provider-exceptions", calculationResultItems.AnyWithNullCheck() ? calculationResultItems.Count(c => !string.IsNullOrWhiteSpace(c.ExceptionMessage)) : 0 }, }; _telemetry.TrackEvent("CalculationRunProvider", new Dictionary <string, string>() { { "specificationId", specificationId }, }, metrics ); if (calculationResultItems.AnyWithNullCheck() && calculationResultItems.Count() > 0) { _logger.Verbose($"Processed results for {calculationResultItems.Count()} calcs in {stopwatch.ElapsedMilliseconds}ms ({stopwatch.ElapsedMilliseconds / calculationResultItems.Count(): 0.0000}ms)"); } else { _logger.Information("There are no calculations to executed for specification ID {specificationId}", specificationId); } byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes($"{provider.Id}-{specificationId}"); ProviderResult providerResult = new ProviderResult { Id = Convert.ToBase64String(plainTextBytes), Provider = provider, SpecificationId = specificationId }; if (calculationResultItems.AnyWithNullCheck()) { foreach (CalculationResult calcResult in calculationResultItems) { CalculationSummaryModel calculationSummaryModel = calculations.First(c => c.Id == calcResult.Calculation.Id); calcResult.CalculationType = calculationSummaryModel.CalculationType; calcResult.CalculationDataType = calculationSummaryModel.CalculationValueType.ToCalculationDataType(); if (calcResult.CalculationDataType == CalculationDataType.Decimal && Decimal.Equals(decimal.MinValue, calcResult.Value)) { // The default for the calculation is to return Decimal.MinValue - if this is the case, then subsitute a 0 value as the result, instead of the negative number. calcResult.Value = 0; } } } //we need a stable sort of results to enable the cache checks by overall SHA hash on the results json providerResult.CalculationResults = calculationResultContainer.CalculationResults?.OrderBy(_ => _.Calculation.Id).ToList(); providerResult.FundingLineResults = calculationResultContainer.FundingLineResults.OrderBy(_ => _.FundingLine.Id).ToList(); return(providerResult); }
public void CalculateProviderResult_WhenCalculationsAreNotEmpty_ShouldReturnCorrectResult() { // Arrange List <Reference> policySpecificationsForFundingCalc = new List <Reference>() { new Reference("Spec1", "SpecOne"), new Reference("Spec2", "SpecTwo") }; Reference fundingCalcReference = new Reference("CalcF1", "Funding calc 1"); Reference numbercalcReference = new Reference("CalcF2", "Funding calc 2"); Reference booleancalcReference = new Reference("CalcF3", "Funding calc 3"); Reference fundingLineCalcReference = new Reference("FL1", "Funding line calc 1"); CalculationResult fundingCalcReturned = new CalculationResult() { Calculation = fundingCalcReference, Value = 10000 }; CalculationResult fundingCalcReturned2 = new CalculationResult() { Calculation = numbercalcReference, Value = 20000 }; CalculationResult fundingCalcReturned3 = new CalculationResult() { Calculation = booleancalcReference, Value = true }; CalculationResultContainer calculationResultContainer = new CalculationResultContainer(); List <CalculationResult> calculationResults = new List <CalculationResult>() { fundingCalcReturned, fundingCalcReturned2, fundingCalcReturned3 }; calculationResultContainer.CalculationResults = calculationResults; string fundingStreamId = "FS1"; FundingLineResult fundingLineResult = new FundingLineResult { Value = 1000, FundingLine = fundingLineCalcReference, FundingLineFundingStreamId = fundingStreamId }; List <FundingLineResult> fundingLineResults = new List <FundingLineResult> { fundingLineResult }; calculationResultContainer.FundingLineResults = fundingLineResults; IAllocationModel mockAllocationModel = Substitute.For <IAllocationModel>(); mockAllocationModel .Execute(Arg.Any <Dictionary <string, ProviderSourceDataset> >(), Arg.Any <ProviderSummary>()) .Returns(calculationResultContainer); CalculationEngine calculationEngine = CreateCalculationEngine(); ProviderSummary providerSummary = CreateDummyProviderSummary(); BuildProject buildProject = CreateBuildProject(); var nonMatchingCalculationModel = new CalculationSummaryModel() { Id = "Non matching calculation", Name = "Non matching calculation", CalculationType = CalculationType.Template, CalculationValueType = CalculationValueType.Number }; IEnumerable <CalculationSummaryModel> calculationSummaryModels = new[] { new CalculationSummaryModel() { Id = fundingCalcReference.Id, Name = fundingCalcReference.Name, CalculationType = CalculationType.Template, CalculationValueType = CalculationValueType.Number }, new CalculationSummaryModel() { Id = numbercalcReference.Id, Name = numbercalcReference.Name, CalculationType = CalculationType.Template, CalculationValueType = CalculationValueType.Number }, new CalculationSummaryModel() { Id = booleancalcReference.Id, Name = booleancalcReference.Name, CalculationType = CalculationType.Template, CalculationValueType = CalculationValueType.Boolean }, nonMatchingCalculationModel }; // Act var calculateProviderResults = calculationEngine.CalculateProviderResults(mockAllocationModel, buildProject.SpecificationId, calculationSummaryModels, providerSummary, new Dictionary <string, ProviderSourceDataset>()); ProviderResult result = calculateProviderResults; // Assert result.Provider.Should().Be(providerSummary); result.SpecificationId.Should().BeEquivalentTo(buildProject.SpecificationId); result.Id.Should().BeEquivalentTo(GenerateId(providerSummary.Id, buildProject.SpecificationId)); result.CalculationResults.Should().HaveCount(3); result.FundingLineResults.Should().HaveCount(1); CalculationResult fundingCalcResult = result.CalculationResults.First(cr => cr.Calculation.Id == fundingCalcReference.Id); fundingCalcResult.Calculation.Should().BeEquivalentTo(fundingCalcReference); fundingCalcResult.CalculationType.Should().BeEquivalentTo(CalculationType.Template); fundingCalcResult.Value.Should().Be(fundingCalcReturned.Value); fundingCalcResult.CalculationDataType.Should().Be(CalculationDataType.Decimal); CalculationResult numberCalcResult = result.CalculationResults.First(cr => cr.Calculation.Id == numbercalcReference.Id); numberCalcResult.Calculation.Should().BeEquivalentTo(numbercalcReference); numberCalcResult.CalculationType.Should().BeEquivalentTo(CalculationType.Template); numberCalcResult.Value.Should().Be(fundingCalcReturned2.Value); numberCalcResult.CalculationDataType.Should().Be(CalculationDataType.Decimal); CalculationResult booleanCalcResult = result.CalculationResults.First(cr => cr.Calculation.Id == booleancalcReference.Id); booleanCalcResult.Calculation.Should().BeEquivalentTo(booleancalcReference); booleanCalcResult.CalculationType.Should().BeEquivalentTo(CalculationType.Template); booleanCalcResult.Value.Should().Be(fundingCalcReturned3.Value); booleanCalcResult.CalculationDataType.Should().Be(CalculationDataType.Boolean); FundingLineResult fundingLineCalcResult = result.FundingLineResults.First(cr => cr.FundingLine.Id == fundingLineCalcReference.Id); fundingLineCalcResult.FundingLine.Should().BeEquivalentTo(fundingLineCalcReference); fundingLineCalcResult.Value.Should().Be(fundingLineResult.Value); fundingLineCalcResult.FundingLineFundingStreamId.Should().Be(fundingStreamId); }