示例#1
0
        public void CheckPrerequisitesForApproveSpecificationToBeApproved_WhenPreReqsValidationErrors_ThrowsException()
        {
            string specificationId = NewRandomString();

            GivenTheMessageHasTheSpecificationId(specificationId);
            AndTheMessageIsOtherwiseValid();
            AndCalculationEngineApproveSpecificationRunning(specificationId);
            AndRetrieveJobAndCheckCanBeProcessedSuccessfully(_ => _.WithJobId(_jobId));

            Func <Task> invocation = WhenAllProvidersResultsAreApproved;

            invocation
            .Should()
            .Throw <Exception>()
            .And
            .Message
            .Should()
            .Be($"Specification with id: '{specificationId} has prerequisites which aren't complete.");

            string[] prereqValidationErrors = new string[] { $"{JobConstants.DefinitionNames.RefreshFundingJob} is still running" };

            _logger.Received(1)
            .Error($"{JobConstants.DefinitionNames.RefreshFundingJob} is still running");

            _jobManagement
            .Received(1)
            .UpdateJobStatus(_jobId, 0, false, string.Join(", ", prereqValidationErrors));
        }
        public void CheckPrerequisitesForAllProvidersToBePublished_WhenPreReqsValidationErrors_ThrowsException()
        {
            GivenJobCanBeProcessed();
            AndSpecification();
            AndCalculationResultsBySpecificationId();
            AndTemplateMetadataContents();
            AndPublishedProviders();
            AndCalculationEngineRunningForPublishAllProviders();

            Func <Task> invocation = WhenPublishAllProvidersMessageReceivedWithJobId;

            invocation
            .Should()
            .Throw <Exception>()
            .And
            .Message
            .Should()
            .Be($"Specification with id: '{SpecificationId} has prerequisites which aren't complete.");

            string[] prereqValidationErrors = new string[] { $"{JobConstants.DefinitionNames.RefreshFundingJob} is still running" };

            _jobManagement
            .Received(1)
            .UpdateJobStatus(JobId, 0, false, string.Join(", ", prereqValidationErrors));
        }
示例#3
0
        public async Task QueueCsvGenerationMessages_GivenSpecificationSummariesFoundAndHasNewResults_CreatesNewMessage()
        {
            //Arrange
            IEnumerable <SpecModel.SpecificationSummary> specificationSummaries = new[]
            {
                new SpecModel.SpecificationSummary {
                    Id = specificationId
                }
            };

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaries()
            .Returns(new ApiResponse <IEnumerable <SpecModel.SpecificationSummary> >(HttpStatusCode.OK, specificationSummaries));

            ICalculationResultsRepository calculationResultsRepository = CreateResultsRepository();

            calculationResultsRepository
            .CheckHasNewResultsForSpecificationIdAndTime(
                Arg.Is(specificationId),
                Arg.Any <DateTimeOffset>())
            .Returns(true);

            ILogger logger = CreateLogger();

            IJobManagement jobManagement = CreateJobManagement();

            IBlobClient blobClient = CreateBlobClient();

            blobClient
            .DoesBlobExistAsync($"{CalculationResultsReportFilePrefix}-{specificationId}", CalcsResultsContainerName)
            .Returns(true);

            ResultsService resultsService = CreateResultsService(
                logger,
                specificationsApiClient: specificationsApiClient,
                resultsRepository: calculationResultsRepository,
                jobManagement: jobManagement,
                blobClient: blobClient);

            //Act
            await resultsService.QueueCsvGenerationMessages();

            //Assert
            await
            jobManagement
            .Received(1)
            .QueueJob(
                Arg.Is <JobCreateModel>(_ =>
                                        _.JobDefinitionId == JobConstants.DefinitionNames.GenerateCalcCsvResultsJob &&
                                        _.Properties["specification-id"] == specificationId));

            logger
            .Received()
            .Information($"Found new calculation results for specification id '{specificationId}'");
        }
示例#4
0
        public async Task ReIndexesAllPublishedProvidersIfJobCanBeProcessed()
        {
            Message message = new Message();

            message.UserProperties.Add("jobId", JobId);

            _jobManagement.RetrieveJobAndCheckCanBeProcessed(JobId)
            .Returns(NewJobViewModel());

            await _service.Run(message);

            await _jobManagement
            .Received(1)
            .UpdateJobStatus(JobId, 0, 0, null, null);

            await _publishedFundingRepository
            .Received(1)
            .AllPublishedProviderBatchProcessing(Arg.Any <Func <List <PublishedProvider>, Task> >(), Arg.Is(1000), null);

            await _jobManagement
            .Received(1)
            .UpdateJobStatus(JobId, 0, 0, true, null);
        }
示例#5
0
        public async Task RegenerateProviderSourceDatasets_GivenSpecificationId_ThenCallJobServiceToProcess()
        {
            // Arrange
            IDatasetRepository datasetRepository = CreateDatasetsRepository();

            datasetRepository
            .GetDefinitionSpecificationRelationshipsByQuery(Arg.Any <Expression <Func <DocumentEntity <DefinitionSpecificationRelationship>, bool> > >())
            .Returns(new List <DefinitionSpecificationRelationship>
            {
                new DefinitionSpecificationRelationship {
                    DatasetVersion = new DatasetRelationshipVersion {
                        Id = "DSRV1", Version = 1
                    },
                    Specification = new Common.Models.Reference {
                        Id = SpecificationId, Name = "SpecAbc"
                    }
                }
            });
            datasetRepository
            .GetDatasetsByQuery(Arg.Any <Expression <Func <DocumentEntity <Dataset>, bool> > >())
            .Returns(new List <Dataset>
            {
                new Dataset {
                    Id = "DS1"
                }
            });

            IJobManagement jobManagement = CreateJobManagement();

            DatasetService service = CreateDatasetService(datasetRepository: datasetRepository, jobManagement: jobManagement);

            // Act
            await service.RegenerateProviderSourceDatasets(SpecificationId, null, null);

            // Assert
            await jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(j =>
                                              j.JobDefinitionId == "MapDatasetJob" &&
                                              j.Properties.ContainsKey("session-id") &&
                                              j.Properties["session-id"] == SpecificationId));
        }
        public async Task ReIndex_CreatesReIndexPublishedProviderJob()
        {
            Reference user = NewUser(_ => _.WithId(NewRandomString())
                                     .WithName(NewRandomString()));
            string correlationId = NewRandomString();

            IActionResult result = await WhenThePublishedProviderVersionsAreReIndexed(user, correlationId);

            result
            .Should()
            .BeOfType <NoContentResult>();

            await _jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(_ =>
                                              _.CorrelationId == correlationId &&
                                              _.InvokerUserId == user.Id &&
                                              _.InvokerUserDisplayName == user.Name &&
                                              _.JobDefinitionId == JobConstants.DefinitionNames.ReIndexPublishedProvidersJob));
        }
        public async Task SaveProviderResults_WhenExcludedResultsAndIsNewProviderCalculationResultsIndexEnabled_ThenResultsSavedToCosmosSavesNull()
        {
            // Arrange
            ICosmosRepository cosmosRepository = CreateCosmosRepository();
            IJobManagement    jobManagement    = CreateJobManagement();

            ProviderResultsRepository repo = CreateProviderResultsRepository(
                cosmosRepository,
                jobManagement: jobManagement);

            SpecificationSummary specificationSummary = new SpecificationSummary
            {
                Name          = "Specification 1",
                FundingPeriod = new Reference()
            };

            IEnumerable <ProviderResult> results = new List <ProviderResult>
            {
                new ProviderResult
                {
                    CalculationResults = new List <CalculationResult>
                    {
                        new CalculationResult
                        {
                            Calculation = new Reference {
                                Id = "calc1", Name = "calculation one"
                            },
                            CalculationType = Models.Calcs.CalculationType.Template,
                            Value           = null
                        }
                    },
                    FundingLineResults = new List <FundingLineResult>
                    {
                        new FundingLineResult
                        {
                            FundingLine = new Reference {
                                Id = "fl1", Name = "funding line one"
                            },
                            FundingLineFundingStreamId = "FS1",
                            Value = null
                        }
                    },
                    Id       = Guid.NewGuid().ToString(),
                    Provider = new ProviderSummary
                    {
                        Id                  = "prov1",
                        Name                = "Provider 1",
                        ProviderType        = "TYpe 1",
                        ProviderSubType     = "Sub type 1",
                        Authority           = "Authority",
                        UKPRN               = "ukprn123",
                        URN                 = "urn123",
                        EstablishmentNumber = "en123",
                        UPIN                = "upin123",
                        DateOpened          = DateTime.Now
                    },
                    SpecificationId = "spec1"
                }
            };

            // Act
            await repo.SaveProviderResults(results, specificationSummary, 1, 1, _user, _correlationId, _jobId);

            // Assert
            await cosmosRepository.Received(1).UpsertAsync <ProviderResult>(
                Arg.Any <ProviderResult>(),
                Arg.Any <string>(),
                Arg.Is <bool>(false),
                Arg.Is <bool>(false));

            await jobManagement.Received(1).QueueJob(Arg.Is <JobCreateModel>(_ =>
                                                                             _.JobDefinitionId == JobConstants.DefinitionNames.SearchIndexWriterJob &&
                                                                             _.ParentJobId == _jobId &&
                                                                             _.Properties["specification-id"] == specificationSummary.GetSpecificationId() &&
                                                                             _.Properties["specification-name"] == specificationSummary.Name &&
                                                                             _.Properties["index-writer-type"] == SearchIndexWriterTypes.ProviderCalculationResultsIndexWriter &&
                                                                             _.MessageBody == JsonConvert.SerializeObject(results.Select(x => x.Provider.Id))));
        }
        public async Task SaveProviderResults_WhenResultsAndIsNewProviderCalculationResultsIndexEnabled_ThenQueueSearchIndexWriterJob()
        {
            // Arrange
            ICosmosRepository cosmosRepository = CreateCosmosRepository();
            IJobManagement    jobManagement    = CreateJobManagement();

            ProviderResultsRepository repo = CreateProviderResultsRepository(
                cosmosRepository,
                jobManagement: jobManagement);

            SpecificationSummary specificationSummary = new SpecificationSummary
            {
                Id            = NewRandomString(),
                Name          = NewRandomString(),
                FundingPeriod = new Reference
                {
                    Id = NewRandomString()
                },
                LastEditedDate = new RandomDateTime(),
                FundingStreams = new[]
                {
                    new Reference
                    {
                        Id = NewRandomString()
                    },
                    new Reference
                    {
                        Id = NewRandomString()
                    },
                    new Reference
                    {
                        Id = NewRandomString()
                    }
                }
            };

            IEnumerable <ProviderResult> results = new List <ProviderResult>
            {
                new ProviderResult
                {
                    CalculationResults = new List <CalculationResult>
                    {
                        new CalculationResult
                        {
                            Calculation = new Reference {
                                Id = "calc1", Name = "calculation one"
                            },
                            CalculationType = CalculationType.Template,
                            Value           = 1112.3M
                        }
                    },
                    FundingLineResults = new List <FundingLineResult>
                    {
                        new FundingLineResult
                        {
                            FundingLine = new Reference {
                                Id = "fl1", Name = "funding line one"
                            },
                            FundingLineFundingStreamId = "FS1",
                            Value = 112.3M
                        }
                    },
                    Id       = Guid.NewGuid().ToString(),
                    Provider = new ProviderSummary
                    {
                        Id                  = "prov1",
                        Name                = "Provider 1",
                        ProviderType        = "TYpe 1",
                        ProviderSubType     = "Sub type 1",
                        Authority           = "Authority",
                        UKPRN               = "ukprn123",
                        URN                 = "urn123",
                        EstablishmentNumber = "en123",
                        UPIN                = "upin123",
                        DateOpened          = DateTime.Now
                    },
                    SpecificationId = "spec1"
                }
            };

            // Act
            await repo.SaveProviderResults(results, specificationSummary, 1, 1, _user, _correlationId, _jobId);

            // Assert
            await jobManagement.Received(1).QueueJob(Arg.Is <JobCreateModel>(_ =>
                                                                             _.JobDefinitionId == JobConstants.DefinitionNames.SearchIndexWriterJob &&
                                                                             _.Properties["specification-id"] == specificationSummary.GetSpecificationId() &&
                                                                             _.Properties["specification-name"] == specificationSummary.Name &&
                                                                             _.Properties["index-writer-type"] == SearchIndexWriterTypes.ProviderCalculationResultsIndexWriter &&
                                                                             _.ParentJobId == _jobId &&
                                                                             _.MessageBody == JsonConvert.SerializeObject(results.Select(x => x.Provider.Id))));

            await _resultsApiClient.Received(1)
            .QueueMergeSpecificationInformationJob(Arg.Is <MergeSpecificationInformationRequest>(_ =>
                                                                                                 _.SpecificationInformation.Id == specificationSummary.Id &&
                                                                                                 _.SpecificationInformation.Name == specificationSummary.Name &&
                                                                                                 _.SpecificationInformation.LastEditDate == specificationSummary.LastEditedDate &&
                                                                                                 _.SpecificationInformation.FundingStreamIds.SequenceEqual(specificationSummary.FundingStreams.Select(fs => fs.Id).ToArray()) &&
                                                                                                 _.SpecificationInformation.FundingPeriodId == specificationSummary.FundingPeriod.Id &&
                                                                                                 _.ProviderIds.SequenceEqual(new[] { "prov1" })));
        }
示例#9
0
 private async Task ThenTheDeleteSpecificationJobIsCreated(Expression <Predicate <JobCreateModel> > expectedJob)
 {
     await _jobs.Received(1).QueueJob(
         Arg.Is(expectedJob));
 }
示例#10
0
 private async Task ThenProviderSnapshotDataLoadJobWasCreated(Expression <Predicate <JobCreateModel> > expectedJob)
 {
     await _jobManagement.Received(1).QueueJob(
         Arg.Is(expectedJob));
 }
示例#11
0
 private async Task ThenTheAssignTemplateCalculationJobWasCreated(Expression <Predicate <JobCreateModel> > expectedJob)
 {
     await _jobs.Received(1).QueueJob(
         Arg.Is(expectedJob));
 }
示例#12
0
        public async Task CreateAdditionalCalculation_GivenCalcSaves_ReturnsOKObjectResult()
        {
            //Arrange
            string cacheKey = $"{CacheKeys.CalculationsMetadataForSpecification}{SpecificationId}";

            CalculationCreateModel model = CreateCalculationCreateModel();

            Reference author = CreateAuthor();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .CreateDraftCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            IJobManagement jobManagement = CreateJobManagement();

            jobManagement
            .QueueJob(Arg.Any <JobCreateModel>())
            .Returns(new Job {
                Id = "job-id-1"
            });

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(SpecificationId))
            .Returns(new ApiResponse <SpecificationSummary>(
                         HttpStatusCode.OK,
                         new SpecificationSummary {
                Id            = SpecificationId,
                FundingPeriod = new FundingPeriod {
                    Id = FundingPeriodId
                }
            }
                         ));

            ILogger logger = CreateLogger();

            ICacheProvider cacheProvider = CreateCacheProvider();

            ICodeContextCache codeContextCache = Substitute.For <ICodeContextCache>();

            IResultsApiClient resultsApiClient = CreateResultsApiClient();

            CalculationService calculationService = CreateCalculationService(
                calculationsRepository: calculationsRepository,
                calculationVersionRepository: versionRepository,
                searchRepository: searchRepository,
                jobManagement: jobManagement,
                logger: logger,
                cacheProvider: cacheProvider,
                specificationsApiClient: specificationsApiClient,
                codeContextCache: codeContextCache,
                resultsApiClient: resultsApiClient);

            IEnumerable <CalculationIndex> indexedCalculations = null;

            await
            searchRepository
            .Index(Arg.Do <IEnumerable <CalculationIndex> >(m =>
                                                            indexedCalculations = m
                                                            ));

            CalculationVersion savedCalculationVersion = null;

            await
            versionRepository
            .SaveVersion(Arg.Do <CalculationVersion>(m => savedCalculationVersion = m));

            //Act
            IActionResult result = await calculationService.CreateAdditionalCalculation(SpecificationId, model, author, CorrelationId);

            //Assert
            result
            .Should()
            .BeAssignableTo <OkObjectResult>();

            Calculation calculation = (result as OkObjectResult).Value as Calculation;

            await
            jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(
                          m =>
                          m.InvokerUserDisplayName == Username &&
                          m.InvokerUserId == UserId &&
                          m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationJob &&
                          m.Properties["specification-id"] == SpecificationId
                          ));

            logger
            .Received(1)
            .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' created with id: 'job-id-1'"));


            await
            versionRepository
            .Received(1)
            .SaveVersion(Arg.Is <CalculationVersion>(m =>
                                                     m.PublishStatus == Models.Versioning.PublishStatus.Draft &&
                                                     m.Author.Id == UserId &&
                                                     m.Author.Name == Username &&
                                                     m.Date.Date == DateTimeOffset.Now.Date &&
                                                     m.Version == 1 &&
                                                     m.SourceCode == model.SourceCode &&
                                                     m.Description == model.Description &&
                                                     m.ValueType == model.ValueType &&
                                                     m.CalculationType == CalculationType.Additional &&
                                                     m.WasTemplateCalculation == false &&
                                                     m.Namespace == CalculationNamespace.Additional &&
                                                     m.Name == model.Name &&
                                                     m.SourceCodeName == new VisualBasicTypeIdentifierGenerator().GenerateIdentifier(model.Name) &&
                                                     m.DataType == CalculationDataType.Decimal
                                                     ));


            await searchRepository
            .Received(1)
            .Index(Arg.Any <IEnumerable <CalculationIndex> >());

            indexedCalculations
            .Should()
            .BeEquivalentTo(new List <CalculationIndex>()
            {
                new CalculationIndex()
                {
                    CalculationType   = "Additional",
                    Description       = "test description",
                    FundingStreamId   = "fs-1",
                    FundingStreamName = model.FundingStreamName,
                    Id                     = model.Id,
                    Name                   = model.Name,
                    Namespace              = "Additional",
                    SpecificationId        = "spec-id-1",
                    SpecificationName      = "spec-id-1_specificationName",
                    Status                 = "Draft",
                    ValueType              = "Currency",
                    WasTemplateCalculation = false,
                    LastUpdatedDate        = savedCalculationVersion.Date,
                }
            });

            //!string.IsNullOrWhiteSpace(m.First().Id) &&
            //m.First().Name == model.Name &&
            //m.First().SpecificationId == SpecificationId &&
            //m.First().SpecificationName == model.SpecificationName &&
            //m.First().ValueType == model.ValueType.ToString() &&
            //m.First().CalculationType == CalculationType.Additional.ToString() &&
            //m.First().Namespace == CalculationNamespace.Additional.ToString() &&
            //m.First().FundingStreamId == model.FundingStreamId &&
            //m.First().FundingStreamName == model.FundingStreamName &&
            //m.First().WasTemplateCalculation == false &&
            //m.First().Description == model.Description &&
            //m.First().Status == calculation.Current.PublishStatus.ToString()

            await
            cacheProvider
            .Received(1)
            .RemoveAsync <List <CalculationMetadata> >(Arg.Is(cacheKey));

            await codeContextCache
            .Received(1)
            .QueueCodeContextCacheUpdate(SpecificationId);
        }
示例#13
0
 private async Task ThenTheApproveAllCalculationsJobIsCreated(Expression <Predicate <JobCreateModel> > expectedJob)
 {
     await _jobs.Received(1).QueueJob(
         Arg.Is(expectedJob));
 }
示例#14
0
 private void AndTheJobWasAddedForTheJobId(Expression <Predicate <JobLogUpdateModel> > jobLogMatching, int times = 1)
 {
     _jobs
     .Received(times)
     .AddJobLog(_jobId, Arg.Is(jobLogMatching));
 }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameButCreatingJobReturnsNull_LogsError()
        {
            // Arrange
            const string specificationId = "spec-id";

            SpecificationVersionComparisonModel specificationVersionComparison = new SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Name = "any-name"
                },
                Previous = new SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calcs = new[]
            {
                new Calculation
                {
                    SpecificationId = "spec-id",
                    Id      = "any-id",
                    Current = new CalculationVersion
                    {
                        Author          = new Reference(UserId, Username),
                        Date            = DateTimeOffset.Now,
                        PublishStatus   = PublishStatus.Draft,
                        SourceCode      = "source code",
                        Version         = 1,
                        Name            = "any name",
                        CalculationType = CalculationType.Template
                    }
                }
            };

            BuildProject buildProject = new BuildProject
            {
                Id = "build-project-1",
                SpecificationId = specificationId
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calcs);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            IJobManagement jobManagement = CreateJobManagement();

            jobManagement
            .QueueJob(Arg.Any <JobCreateModel>())
            .Returns((Job)null);


            CalculationService service = CreateCalculationService(
                calculationsRepository,
                logger,
                buildProjectsService: buildProjectsService,
                jobManagement: jobManagement);

            // Act
            Func <Task> test = async() => await service.Run(message);

            // Assert
            test
            .Should()
            .ThrowExactly <RetriableException>()
            .Which
            .Message
            .Should()
            .Be($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'");

            await
            jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(
                          m =>
                          m.InvokerUserDisplayName == Username &&
                          m.InvokerUserId == UserId &&
                          m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationJob &&
                          m.Properties["specification-id"] == specificationId &&
                          m.Trigger.EntityId == specificationId &&
                          m.Trigger.EntityType == "Specification" &&
                          m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'"
                          ));

            logger
            .Received(1)
            .Error(Arg.Is($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'"));
        }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameAndSourceCodeContainsCalculationAggregate_SavesChangesEnsuresGenerateAggregationsJobCreated()
        {
            // Arrange
            const string specificationId = "spec-id";

            SpecificationVersionComparisonModel specificationVersionComparison = new SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Name = "any-name"
                },
                Previous = new SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calcs = new[]
            {
                new Calculation
                {
                    SpecificationId = "spec-id",
                    Id      = "any-id",
                    Current = new CalculationVersion
                    {
                        Author          = new Reference(UserId, Username),
                        Date            = DateTimeOffset.Now,
                        PublishStatus   = PublishStatus.Draft,
                        SourceCode      = "return Min(calc1)",
                        Version         = 1,
                        Name            = "any name",
                        CalculationType = CalculationType.Template
                    }
                }
            };

            BuildProject buildProject = new BuildProject
            {
                Id = "build-project-1",
                SpecificationId = specificationId
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calcs);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            IJobManagement jobManagement = CreateJobManagement();

            jobManagement
            .QueueJob(Arg.Any <JobCreateModel>())
            .Returns(new Job {
                Id = "job-id-1", JobDefinitionId = JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob
            });


            CalculationService service = CreateCalculationService(
                calculationsRepository,
                logger,
                buildProjectsService: buildProjectsService,
                jobManagement: jobManagement);

            // Act
            await service.Run(message);

            // Assert
            await
            jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(
                          m =>
                          m.InvokerUserDisplayName == Username &&
                          m.InvokerUserId == UserId &&
                          m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob &&
                          m.Properties["specification-id"] == specificationId &&
                          m.Trigger.EntityId == specificationId &&
                          m.Trigger.EntityType == "Specification" &&
                          m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'"
                          ));

            logger
            .Received(1)
            .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob}' created with id: 'job-id-1'"));
        }
 private void AndTheJobsStartWasLogged()
 {
     _jobManagement
     .Received(1)
     .UpdateJobStatus(_jobId, 0, 0, null, null);
 }