示例#1
0
        public async Task CacheReloadServiceReloadIsSuccessfulForCreate()
        {
            // arrange
            var cancellationToken = new CancellationToken(false);
            var expectedValidCmsApiSharedContentModel = BuildValidCmsApiSharedContentModel();

            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiSharedContentModel>(A <string> .Ignored, A <Guid> .Ignored)).Returns(expectedValidCmsApiSharedContentModel);
            A.CallTo(() => fakeEventMessageService.UpdateAsync(A <CmsApiSharedContentModel> .Ignored))
            .Returns(HttpStatusCode.NotFound);
            A.CallTo(() => fakeEventMessageService.CreateAsync(A <CmsApiSharedContentModel> .Ignored))
            .Returns(HttpStatusCode.Created);

            A.CallTo(() => fakeEventMessageService.DeleteAsync(A <Guid> .Ignored)).Returns(HttpStatusCode.OK);

            var cacheReloadService = new CacheReloadService(fakeLogger, fakeEventMessageService, fakeCmsApiService,
                                                            fakeContentTypeMappingService, _config);

            // act
            await cacheReloadService.Reload(cancellationToken).ConfigureAwait(false);

            // assert
            A.CallTo(() => fakeContentTypeMappingService.AddMapping(A <string> .Ignored, A <Type> .Ignored))
            .MustHaveHappenedOnceOrMore();
            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiSharedContentModel>(A <string> .Ignored, A <Guid> .Ignored))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeEventMessageService.UpdateAsync(A <CmsApiSharedContentModel> .Ignored))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeEventMessageService.CreateAsync(A <CmsApiSharedContentModel> .Ignored))
            .MustHaveHappenedOnceExactly();
        }
示例#2
0
        public async Task ReloadSharedContent(CancellationToken stoppingToken)
        {
            await staticContentDocumentService.PurgeAsync().ConfigureAwait(false);

            var contentIds = cmsApiClientOptions.ContentIds.Split(",", StringSplitOptions.RemoveEmptyEntries);

            foreach (var contentId in contentIds)
            {
                if (stoppingToken.IsCancellationRequested)
                {
                    logger.LogWarning("Reload shared-content cache cancelled");

                    return;
                }

                var apiDataModel = await cmsApiService.GetItemAsync <StaticContentItemApiDataModel>("sharedcontent", new Guid(contentId)).ConfigureAwait(false);

                if (apiDataModel == null)
                {
                    logger.LogError($"Shared-content: {contentId} not found in API response");
                }

                var staticContentItemModel = mapper.Map <StaticContentItemModel>(apiDataModel);

                if (!TryValidateModel(staticContentItemModel))
                {
                    logger.LogError($"Validation failure for {staticContentItemModel.Title} - {staticContentItemModel.Url}");

                    return;
                }

                await staticContentDocumentService.UpsertAsync(staticContentItemModel).ConfigureAwait(false);
            }
        }
        public async Task <HttpStatusCode> TransformItemActivity([ActivityTrigger] Uri?url)
        {
            _ = url ?? throw new ArgumentNullException(nameof(url));

            logger.LogInformation($"Loading Job Group item: {url}");
            var lmiSoc = await cmsApiService.GetItemAsync <LmiSoc>(url).ConfigureAwait(false);

            logger.LogInformation($"Transforming Job Group item for {url} to cache");
            var jobGroup = mapper.Map <JobGroupModel>(lmiSoc);

            if (jobGroup != null)
            {
                var existingJobGroup = await jobGroupDocumentService.GetAsync(w => w.Soc == jobGroup.Soc, jobGroup.Soc.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);

                if (existingJobGroup != null)
                {
                    jobGroup.Etag = existingJobGroup.Etag;
                }

                logger.LogInformation($"Upserting Job Groups item: {jobGroup.Soc} / {url}");
                return(await jobGroupDocumentService.UpsertAsync(jobGroup).ConfigureAwait(false));
            }

            return(HttpStatusCode.BadRequest);
        }
        public async Task ReloadIsCancelled()
        {
            //Arrange
            var cancellationToken = new CancellationToken(true);
            var service           = new StaticContentReloadService(fakeLogger, fakeMapper, fakeStaticContentDocumentService, fakeCmsApiService, fakeCmsApiClientOptions);

            //Act
            await service.Reload(cancellationToken).ConfigureAwait(false);

            //Assert
            A.CallTo(() => fakeCmsApiService.GetItemAsync <StaticContentItemApiDataModel>(A <string> .Ignored, A <Guid> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeMapper.Map <StaticContentItemModel>(A <StaticContentItemApiDataModel> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeStaticContentDocumentService.UpsertAsync(A <StaticContentItemModel> .Ignored)).MustNotHaveHappened();

            Assert.True(true);
        }
        private async Task ReloadConfigurationSetTemplate(CancellationToken stoppingToken)
        {
            if (stoppingToken.IsCancellationRequested)
            {
                logger.LogWarning("Reload configuration set cancelled");

                return;
            }

            var key = ConfigurationSetKeyHelper.ConfigurationSetKey;

            var url          = new Uri($"{cmsApiClientOptions.BaseAddress}/{Constants.ContentTypeForConfigurationSet}/{key}", UriKind.Absolute);
            var apiDataModel = await cmsApiService.GetItemAsync <ConfigurationSetApiDataModel>(url).ConfigureAwait(false);

            if (apiDataModel == null)
            {
                logger.LogError($"Configuration set: {key} not found in API response");
                return;
            }

            if (!apiDataModel.ContentItems.Any())
            {
                logger.LogError($"Configuration set: {key} contains no items");
                return;
            }

            var configurationSetModel = mapper.Map <ConfigurationSetModel>(apiDataModel);

            await configurationSetDocumentService.UpsertAsync(configurationSetModel).ConfigureAwait(false);
        }
示例#6
0
        public async Task ReloadSharedContent(CancellationToken stoppingToken)
        {
            var contentItemKeys = SharedContentKeyHelper.GetSharedContentKeys();

            foreach (var key in contentItemKeys)
            {
                if (stoppingToken.IsCancellationRequested)
                {
                    logger.LogWarning("Reload shared content cache cancelled");

                    return;
                }

                var apiDataModel = await cmsApiService.GetItemAsync <SharedContentItemApiDataModel>("sharedcontent", key).ConfigureAwait(false);

                if (apiDataModel == null)
                {
                    logger.LogError($"shared content: {key} not found in API response");
                }
                else
                {
                    var mappedContentItem = mapper.Map <SharedContentItemModel>(apiDataModel);

                    await sharedContentDocumentService.UpsertAsync(mappedContentItem).ConfigureAwait(false);
                }
            }
        }
        public async Task <CmsApiSharedContentModel>?GetSharedContentAsync()
        {
            logger.LogInformation("Get shared content");
            var summaryList = await cmsApiService.GetItemAsync <CmsApiSharedContentModel>("sharedContent", SharedContent).ConfigureAwait(false);

            logger.LogInformation("Get shared content completed");

            return(summaryList);
        }
示例#8
0
        public async Task JobGroupCacheRefreshServiceReloadIsSuccessful()
        {
            // arrange
            const HttpStatusCode expectedUpsertResult = HttpStatusCode.OK;

            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiSharedContentModel>(A <Uri> .Ignored)).Returns(A.Dummy <CmsApiSharedContentModel>());
            A.CallTo(() => fakeMapper.Map <ContentItemModel>(A <CmsApiSharedContentModel> .Ignored)).Returns(A.Dummy <ContentItemModel>());
            A.CallTo(() => fakeContentItemDocumentService.UpsertAsync(A <ContentItemModel> .Ignored)).Returns(expectedUpsertResult);

            // act
            await sharedContentCacheReloadService.ReloadAsync(new CancellationToken(false)).ConfigureAwait(false);

            // assert
            A.CallTo(() => fakeContentTypeMappingService.AddMapping(A <string> .Ignored, A <Type> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiSharedContentModel>(A <Uri> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeMapper.Map <ContentItemModel>(A <CmsApiSharedContentModel> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeContentItemDocumentService.UpsertAsync(A <ContentItemModel> .Ignored)).MustHaveHappenedOnceExactly();
        }
示例#9
0
        public async Task LmiOrchestrationTriggerTransformItemAsyncIsSuccessful()
        {
            // Arrange
            const HttpStatusCode expectedResult = HttpStatusCode.OK;
            var dummyLmiSoc   = A.Dummy <LmiSoc>();
            var dummyJobgroup = A.Dummy <JobGroupModel>();

            A.CallTo(() => fakeCmsApiService.GetItemAsync <LmiSoc>(A <Uri> .Ignored)).Returns(dummyLmiSoc);
            A.CallTo(() => fakeMapper.Map <JobGroupModel>(A <LmiSoc> .Ignored)).Returns(dummyJobgroup);
            A.CallTo(() => fakeJobGroupDocumentService.GetAsync(A <Expression <Func <JobGroupModel, bool> > > .Ignored, A <string> .Ignored)).Returns(dummyJobgroup);
            A.CallTo(() => fakeJobGroupDocumentService.UpsertAsync(A <JobGroupModel> .Ignored)).Returns(expectedResult);

            // Act
            var result = await lmiOrchestrationTrigger.TransformItemActivity(new Uri("https://somewhere.com", UriKind.Absolute)).ConfigureAwait(false);

            // Assert
            A.CallTo(() => fakeCmsApiService.GetItemAsync <LmiSoc>(A <Uri> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeMapper.Map <JobGroupModel>(A <LmiSoc> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeJobGroupDocumentService.GetAsync(A <Expression <Func <JobGroupModel, bool> > > .Ignored, A <string> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeJobGroupDocumentService.UpsertAsync(A <JobGroupModel> .Ignored)).MustHaveHappenedOnceExactly();
            Assert.Equal(expectedResult, result);
        }
        public async Task SharedContentCacheReloadServiceReloadAllCancellationRequestedCancels()
        {
            //Arrange
            var cancellationToken = new CancellationToken(true);
            var sharedContentCacheReloadService = new SharedContentCacheReloadService(A.Fake <ILogger <SharedContentCacheReloadService> >(), fakeMapper, fakeSharedContentItemDocumentService, fakeCmsApiService);

            //Act
            await sharedContentCacheReloadService.Reload(cancellationToken).ConfigureAwait(false);

            //Assert
            A.CallTo(() => fakeCmsApiService.GetItemAsync <SharedContentItemApiDataModel>(A <string> .Ignored, A <Guid> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeSharedContentItemDocumentService.UpsertAsync(A <SharedContentItemModel> .Ignored)).MustNotHaveHappened();
        }
        public async Task ConfigurationSetReloadServiceReloadCancellationRequestedCancels()
        {
            //Arrange
            var dummyCmsApiClientOptions      = A.Dummy <CmsApiClientOptions>();
            var cancellationToken             = new CancellationToken(true);
            var configurationSetReloadService = new ConfigurationSetReloadService(A.Fake <ILogger <ConfigurationSetReloadService> >(), fakeMapper, fakeConfigurationSetDocumentService, fakeCmsApiService, dummyCmsApiClientOptions, fakeContentTypeMappingService);

            //Act
            await configurationSetReloadService.Reload(cancellationToken).ConfigureAwait(false);

            //Assert
            A.CallTo(() => fakeCmsApiService.GetItemAsync <ConfigurationSetApiDataModel>(A <Uri> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeMapper.Map <ConfigurationSetModel>(A <ConfigurationSetApiDataModel> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeConfigurationSetDocumentService.UpsertAsync(A <ConfigurationSetModel> .Ignored)).MustNotHaveHappened();
        }
示例#12
0
        public async Task <HttpStatusCode> ProcessSharedContentAsync(Guid eventId, Uri?url)
        {
            var apiDataModel = await cmsApiService.GetItemAsync <CmsApiSharedContentModel>(url).ConfigureAwait(false);

            var contentItemModel = mapper.Map <ContentItemModel>(apiDataModel);

            if (contentItemModel == null)
            {
                logger.LogWarning($"Event Id: {eventId} - no shared content for: {url}");
                return(HttpStatusCode.NoContent);
            }

            var contentResult = await contentItemDocumentService.UpsertAsync(contentItemModel).ConfigureAwait(false);

            logger.LogInformation($"Event Id: {eventId} - processed shared content result: {contentResult} - for: {url}");
            return(contentResult);
        }
示例#13
0
        public async Task <HttpStatusCode> ProcessContentAsync(Uri url, Guid contentId)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }

            url = Combine(url.ToString(), "true?checkAncestryById=true"); // This enables the multiDirectional support needed for page locations

            var apiDataModel = await cmsApiService.GetItemAsync <CmsApiDataModel>(url).ConfigureAwait(false);

            var contentPageModel = mapper.Map <ContentPageModel>(apiDataModel);

            if (contentPageModel == null)
            {
                return(HttpStatusCode.NoContent);
            }

            if (!TryValidateModel(contentPageModel))
            {
                return(HttpStatusCode.BadRequest);
            }

            var existingContentPageModel = await contentPageService.GetByIdAsync(contentId).ConfigureAwait(false);

            var contentResult = await eventMessageService.UpdateAsync(contentPageModel).ConfigureAwait(false);

            if (contentResult == HttpStatusCode.NotFound)
            {
                contentResult = await eventMessageService.CreateAsync(contentPageModel).ConfigureAwait(false);
            }

            if (contentResult == HttpStatusCode.OK || contentResult == HttpStatusCode.Created)
            {
                await eventGridService.CompareAndSendEventAsync(existingContentPageModel, contentPageModel).ConfigureAwait(false);

                var contentItemIds = contentPageModel.AllContentItemIds;

                contentItemIds.AddRange(contentPageModel.AllPageLocationIds);

                contentCacheService.AddOrReplace(contentId, contentItemIds);
            }

            return(contentResult);
        }
        public async Task <HttpStatusCode> ProcessContentAsync(Uri url, Guid contentId)
        {
            var apiDataModel = await cmsApiService.GetItemAsync <CmsApiSharedContentModel>(url).ConfigureAwait(false);

            if (apiDataModel == null)
            {
                return(HttpStatusCode.NoContent);
            }
            apiDataModel.Id = apiDataModel.ItemId.Value;
            var contentResult = await eventMessageService.UpdateAsync(apiDataModel).ConfigureAwait(false);

            if (contentResult == HttpStatusCode.NotFound)
            {
                contentResult = await eventMessageService.CreateAsync(apiDataModel).ConfigureAwait(false);
            }


            return(contentResult);
        }
        public async Task <HttpStatusCode> ProcessContentItemAsync(Uri url)
        {
            var apiDataModel = await cmsApiService.GetItemAsync <StaticContentItemApiDataModel>(url).ConfigureAwait(false);

            var staticContentItemModel = mapper.Map <StaticContentItemModel>(apiDataModel);

            if (staticContentItemModel == null)
            {
                return(HttpStatusCode.NoContent);
            }

            if (!TryValidateModel(staticContentItemModel))
            {
                return(HttpStatusCode.BadRequest);
            }

            var contentResult = await configurationSetDocumentService.UpsertAsync(staticContentItemModel).ConfigureAwait(false);

            return(contentResult);
        }
        private async Task ReloadCacheItem(Guid itemId, CancellationToken stoppingToken)
        {
            if (stoppingToken.IsCancellationRequested)
            {
                logger.LogWarning("Reload shared content cancelled");

                return;
            }

            var url          = new Uri($"{cmsApiClientOptions.BaseAddress}/{Constants.ContentTypeSharedContent.ToLowerInvariant()}/{itemId}", UriKind.Absolute);
            var apiDataModel = await cmsApiService.GetItemAsync <CmsApiSharedContentModel>(url).ConfigureAwait(false);

            if (apiDataModel == null)
            {
                logger.LogError($"Shared content: {itemId} not found in API response");
                return;
            }

            var contentItemModel = mapper.Map <ContentItemModel>(apiDataModel);

            await contentItemDocumentService.UpsertAsync(contentItemModel).ConfigureAwait(false);
        }
示例#17
0
        public async Task <HttpStatusCode> ProcessContentAsync(Uri url, Guid contentId)
        {
            var apiDataModel = await cmsApiService.GetItemAsync <CmsApiDataModel>(url).ConfigureAwait(false);

            var contentPageModel = mapper.Map <ContentPageModel>(apiDataModel);

            if (contentPageModel == null)
            {
                return(HttpStatusCode.NoContent);
            }

            if (!TryValidateModel(contentPageModel))
            {
                return(HttpStatusCode.BadRequest);
            }

            var existingContentPageModel = await contentPageService.GetByIdAsync(contentId).ConfigureAwait(false);

            var contentResult = await eventMessageService.UpdateAsync(contentPageModel).ConfigureAwait(false);

            if (contentResult == HttpStatusCode.NotFound)
            {
                contentResult = await eventMessageService.CreateAsync(contentPageModel).ConfigureAwait(false);
            }

            if (contentResult == HttpStatusCode.OK || contentResult == HttpStatusCode.Created)
            {
                await eventGridService.CompareAndSendEventAsync(existingContentPageModel, contentPageModel).ConfigureAwait(false);

                var contentItemIds = contentPageModel.AllContentItemIds;

                contentItemIds.AddRange(contentPageModel.AllPageLocationIds);

                contentCacheService.AddOrReplace(contentId, contentItemIds);
            }

            return(contentResult);
        }
示例#18
0
        public async Task GetAndSaveItemAsync(CmsApiSummaryItemModel item, CancellationToken stoppingToken)
        {
            _ = item ?? throw new ArgumentNullException(nameof(item));
            var url = Combine(item.Url !.ToString(), "true?checkAncestryById=true"); // This enables the multiDirectional support needed for page locations

            try
            {
                logger.LogInformation($"Get details for {item.Title} - {url}");

                var apiDataModel = await cmsApiService.GetItemAsync <CmsApiDataModel>(url).ConfigureAwait(false);

                if (apiDataModel == null)
                {
                    logger.LogWarning($"No details returned from {item.Title} - {url}");

                    return;
                }

                if (stoppingToken.IsCancellationRequested)
                {
                    logger.LogWarning("Process item get and save cancelled");

                    return;
                }

                var contentPageModel = mapper.Map <ContentPageModel>(apiDataModel);

                if (!TryValidateModel(contentPageModel))
                {
                    logger.LogError($"Validation failure for {item.Title} - {url}");

                    return;
                }

                logger.LogInformation($"Updating cache with {item.Title} - {url}");

                var result = await eventMessageService.UpdateAsync(contentPageModel).ConfigureAwait(false);

                if (result == HttpStatusCode.NotFound)
                {
                    logger.LogInformation($"Does not exist, creating cache with {item.Title} - {url}");

                    result = await eventMessageService.CreateAsync(contentPageModel).ConfigureAwait(false);

                    if (result == HttpStatusCode.Created)
                    {
                        logger.LogInformation($"Created cache with {item.Title} - {url}");
                    }
                    else
                    {
                        logger.LogError($"Cache create error status {result} from {item.Title} - {url}");
                    }
                }
                else
                {
                    logger.LogInformation($"Updated cache with {item.Title} - {url}");
                }

                var contentItemIds = contentPageModel.AllContentItemIds;

                contentItemIds.AddRange(contentPageModel.AllPageLocationIds);

                contentCacheService.AddOrReplace(contentPageModel.Id, contentItemIds);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"Error in get and save for {item.Title} - {url}");
            }
        }
        public async Task ProcessMessageAsyncDeleteReturnsSuccess()
        {
            //Arrange
            const HttpStatusCode expectedResult = HttpStatusCode.OK;
            var service = new WebhooksService(fakeLogger, fakeMapper, fakeCmsApiService, fakeConfigurationSetDocumentService);
            var dummyStaticContentItemApiDataModel = A.Dummy <StaticContentItemApiDataModel>();
            var validStaticContentItemModel        = BuildValidStaticContentItemModel();

            A.CallTo(() => fakeConfigurationSetDocumentService.DeleteAsync(A <Guid> .Ignored)).Returns(true);

            //Act
            var result = await service.ProcessMessageAsync(WebhookCacheOperation.Delete, Guid.NewGuid(), Guid.NewGuid(), "https://somewhere.com").ConfigureAwait(false);

            //Assert
            A.CallTo(() => fakeCmsApiService.GetItemAsync <StaticContentItemApiDataModel>(A <Uri> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeMapper.Map <StaticContentItemModel>(A <StaticContentItemApiDataModel> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeConfigurationSetDocumentService.UpsertAsync(A <StaticContentItemModel> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeConfigurationSetDocumentService.DeleteAsync(A <Guid> .Ignored)).MustHaveHappenedOnceExactly();

            Assert.Equal(expectedResult, result);
        }
示例#20
0
        public async Task WebhooksContentServiceProcessContentForSharedContentItemReturnsSuccess()
        {
            // Arrange
            const HttpStatusCode expectedResult = HttpStatusCode.OK;

            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiSharedContentModel>(A <Uri> .Ignored)).Returns(A.Dummy <CmsApiSharedContentModel>());
            A.CallTo(() => fakeMapper.Map <ContentItemModel>(A <CmsApiSharedContentModel> .Ignored)).Returns(A.Dummy <ContentItemModel>());
            A.CallTo(() => fakeContentItemDocumentService.UpsertAsync(A <ContentItemModel> .Ignored)).Returns(expectedResult);

            // Act
            var result = await webhooksContentService.ProcessContentAsync(false, Guid.NewGuid(), null, "https://somewhere.com", MessageContentType.SharedContentItem).ConfigureAwait(false);

            // Assert
            A.CallTo(() => fakeJobGroupCacheRefreshService.ReloadAsync(A <Uri> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeJobGroupCacheRefreshService.ReloadItemAsync(A <Uri> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiSharedContentModel>(A <Uri> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeMapper.Map <ContentItemModel>(A <CmsApiSharedContentModel> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeContentItemDocumentService.UpsertAsync(A <ContentItemModel> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeJobGroupPublishedRefreshService.ReloadAsync(A <Uri> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeJobGroupPublishedRefreshService.ReloadItemAsync(A <Uri> .Ignored)).MustNotHaveHappened();
            A.CallTo(() => fakeEventGridService.SendEventAsync(A <EventGridEventData> .Ignored, A <string> .Ignored, A <string> .Ignored)).MustNotHaveHappened();

            Assert.Equal(expectedResult, result);
        }
示例#21
0
        public async Task CacheReloadServiceReloadIsSuccessfulForCreate()
        {
            // arrange
            const int NumerOfSummaryItems           = 2;
            const int NumberOfDeletions             = 3;
            var       cancellationToken             = new CancellationToken(false);
            var       expectedValidContentPageModel = BuildValidContentPageModel();
            var       fakePagesSummaryItemModels    = BuldFakePagesSummaryItemModel(NumerOfSummaryItems);
            var       fakeCachedContentPageModels   = BuldFakeContentPageModels(NumberOfDeletions);

            A.CallTo(() => fakeCmsApiService.GetSummaryAsync <CmsApiSummaryItemModel>()).Returns(fakePagesSummaryItemModels);
            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiDataModel>(A <Uri> .Ignored)).Returns(A.Fake <CmsApiDataModel>());
            A.CallTo(() => fakeMapper.Map <ContentPageModel>(A <CmsApiDataModel> .Ignored)).Returns(expectedValidContentPageModel);
            A.CallTo(() => fakeEventMessageService.UpdateAsync(A <ContentPageModel> .Ignored)).Returns(HttpStatusCode.NotFound);
            A.CallTo(() => fakeEventMessageService.CreateAsync(A <ContentPageModel> .Ignored)).Returns(HttpStatusCode.Created);
            A.CallTo(() => fakeEventMessageService.GetAllCachedItemsAsync()).Returns(fakeCachedContentPageModels);
            A.CallTo(() => fakeEventMessageService.DeleteAsync(A <Guid> .Ignored)).Returns(HttpStatusCode.OK);
            A.CallTo(() => fakeContentCacheService.AddOrReplace(A <Guid> .Ignored, A <List <Guid> > .Ignored, A <string> .Ignored));

            var cacheReloadService = new CacheReloadService(fakeLogger, fakeMapper, fakeEventMessageService, fakeCmsApiService, fakeContentCacheService, fakeAppRegistryService, fakeContentTypeMappingService, fakeApiCacheService);

            // act
            await cacheReloadService.Reload(cancellationToken).ConfigureAwait(false);

            // assert
            A.CallTo(() => fakeContentTypeMappingService.AddMapping(A <string> .Ignored, A <Type> .Ignored)).MustHaveHappenedOnceOrMore();
            A.CallTo(() => fakeCmsApiService.GetSummaryAsync <CmsApiSummaryItemModel>()).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeContentCacheService.Clear()).MustHaveHappenedOnceExactly();
            A.CallTo(() => fakeCmsApiService.GetItemAsync <CmsApiDataModel>(A <Uri> .Ignored)).MustHaveHappened(NumerOfSummaryItems, Times.Exactly);
            A.CallTo(() => fakeMapper.Map <ContentPageModel>(A <CmsApiDataModel> .Ignored)).MustHaveHappened(NumerOfSummaryItems, Times.Exactly);
            A.CallTo(() => fakeEventMessageService.UpdateAsync(A <ContentPageModel> .Ignored)).MustHaveHappened(NumerOfSummaryItems, Times.Exactly);
            A.CallTo(() => fakeEventMessageService.CreateAsync(A <ContentPageModel> .Ignored)).MustHaveHappened(NumerOfSummaryItems, Times.Exactly);
            A.CallTo(() => fakeEventMessageService.GetAllCachedItemsAsync()).MustHaveHappenedTwiceExactly();
            A.CallTo(() => fakeEventMessageService.DeleteAsync(A <Guid> .Ignored)).MustHaveHappened(NumberOfDeletions, Times.Exactly);
            A.CallTo(() => fakeContentCacheService.AddOrReplace(A <Guid> .Ignored, A <List <Guid> > .Ignored, A <string> .Ignored)).MustHaveHappened(NumerOfSummaryItems, Times.Exactly);
            A.CallTo(() => fakeAppRegistryService.PagesDataLoadAsync()).MustHaveHappenedOnceExactly();
        }