public async Task GetFundingTemplate_GivenFetechingBlobFails_ReturnsInternalServerError()
        {
            //Arrange
            const string fundingStreamId = "PES";
            const string templateVersion = "1.2";
            const string fundingPeriodId = "AY-2020";

            string cacheKey = $"{CacheKeys.FundingTemplatePrefix}{fundingStreamId}-{fundingPeriodId}-{templateVersion}";

            string blobName = $"{fundingStreamId}/{fundingPeriodId}/{templateVersion}.json";

            string template = string.Empty;

            ICacheProvider cacheProvider = CreateCacheProvider();

            cacheProvider
            .GetAsync <string>(Arg.Is(cacheKey))
            .Returns((string)null);

            IFundingTemplateRepository fundingTemplateRepository = CreateFundingTemplateRepository();

            fundingTemplateRepository
            .TemplateVersionExists(Arg.Is(blobName))
            .Returns(true);

            fundingTemplateRepository
            .When(x => x.GetFundingTemplateVersion(Arg.Is(blobName)))
            .Do(x => { throw new Exception(); });

            ILogger logger = CreateLogger();

            FundingTemplateService fundingTemplateService = CreateFundingTemplateService(
                logger,
                cacheProvider: cacheProvider,
                fundingTemplateRepository: fundingTemplateRepository);

            //Act
            ActionResult <string> result = await fundingTemplateService.GetFundingTemplateSourceFile(fundingStreamId, fundingPeriodId, templateVersion);

            //Assert
            result
            .Result
            .Should()
            .BeAssignableTo <InternalServerErrorResult>()
            .Which
            .Value
            .Should()
            .Be($"Error occurred fetching funding template for funding stream id '{fundingStreamId}', funding period id '{fundingPeriodId}' and version '{templateVersion}'");

            logger
            .Received(1)
            .Error(Arg.Any <Exception>(), $"Failed to fetch funding template '{blobName}' from blob storage");
        }
        public async Task SaveFundingTemplate_GivenValidTemplateButFailedToSaveToBlobStorage_ReturnsInternalServerError()
        {
            //Arrange
            const string template        = "a template";
            string       fundingStreamId = NewRandomString();
            string       templateVersion = NewRandomString();
            string       fundingPeriodId = NewRandomString();

            FundingTemplateValidationResult validationResult = new FundingTemplateValidationResult
            {
                TemplateVersion = "1.8",
                FundingStreamId = "PES",
                SchemaVersion   = "1.0",
                FundingPeriodId = "AY-2020"
            };

            string blobName = $"{validationResult.FundingStreamId}/{validationResult.FundingPeriodId}/{validationResult.TemplateVersion}.json";

            IFundingTemplateValidationService fundingTemplateValidationService = CreateFundingTemplateValidationService();

            fundingTemplateValidationService
            .ValidateFundingTemplate(Arg.Is(template), Arg.Is(fundingStreamId), Arg.Is(fundingPeriodId), Arg.Is(templateVersion))
            .Returns(validationResult);

            IFundingTemplateRepository fundingTemplateRepository = CreateFundingTemplateRepository();

            fundingTemplateRepository
            .When(x => x.SaveFundingTemplateVersion(Arg.Is(blobName), Arg.Any <byte[]>()))
            .Do(x => { throw new Exception(); });

            ILogger logger = CreateLogger();

            ITemplateMetadataGenerator templateMetadataGenerator = CreateMetadataGenerator();

            templateMetadataGenerator.Validate(Arg.Is <string>(template))
            .Returns(new FluentValidation.Results.ValidationResult());

            ITemplateMetadataResolver templateMetadataResolver = CreateMetadataResolver("1.0", templateMetadataGenerator);

            FundingTemplateService fundingTemplateService = CreateFundingTemplateService(
                logger,
                fundingTemplateValidationService: fundingTemplateValidationService,
                fundingTemplateRepository: fundingTemplateRepository,
                templateMetadataResolver: templateMetadataResolver);

            //Act
            IActionResult result = await fundingTemplateService.SaveFundingTemplate(createdAtActionName, createdAtControllerName, template, fundingStreamId, fundingPeriodId, templateVersion);

            //Assert
            result
            .Should()
            .BeAssignableTo <InternalServerErrorResult>()
            .Which
            .Value
            .Should()
            .Be("Error occurred uploading funding template");

            logger
            .Received(1)
            .Error(Arg.Any <NonRetriableException>(), Arg.Is($"Failed to save funding template '{blobName}' to blob storage"));
        }