public async Task GetProviderFundingVersionsBody_GivenGetBlobReferenceCausesException_LogsAndReturnsInternalServerError()
        {
            //Arrange
            ILogger     logger     = CreateLogger();
            IBlobClient blobClient = CreateBlobClient();

            blobClient
            .BlobExistsAsync(blobName)
            .Returns(true);

            blobClient
            .GetBlobReferenceFromServerAsync(blobName)
            .Throws(new Exception());

            string errorMessage = $"Failed to fetch blob '{blobName}' from azure storage";

            ProviderFundingVersionService service = CreateProviderFundingVersionService(logger, blobClient);

            //Act
            IActionResult result = await service.GetProviderFundingVersion(providerFundingVersion);

            //Assert
            result
            .Should()
            .BeAssignableTo <InternalServerErrorResult>()
            .Which
            .Value
            .Should()
            .Be(errorMessage);

            logger
            .Received(1)
            .Error(Arg.Any <Exception>(), Arg.Is(errorMessage));
        }
        public async Task GetProviderFundingVersionsBody_GivenNullOrEmptyId_ReturnsBadRequest()
        {
            //Arrange
            string id = "";

            ProviderFundingVersionService service = CreateProviderFundingVersionService();

            //Act
            IActionResult result = await service.GetProviderFundingVersion(id);

            //Assert
            result
            .Should()
            .BeAssignableTo <BadRequestObjectResult>()
            .Which
            .Value
            .Should()
            .Be("Null or empty id provided.");
        }
        public async Task GetProviderFundingVersionsBody_GivenBlobDoesNotExists_ReturnsNotFound()
        {
            //Arrange
            ILogger     logger     = CreateLogger();
            IBlobClient blobClient = CreateBlobClient();

            ProviderFundingVersionService service = CreateProviderFundingVersionService(logger, blobClient);

            //Act
            IActionResult result = await service.GetProviderFundingVersion(providerFundingVersion);

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

            logger
            .Received(1)
            .Error(Arg.Is($"Blob '{blobName}' does not exist."));
        }
        public async Task GetProviderFundingVersionsBody_GivenReturnsFromBlobStorage_ReturnsOK(bool isFileSystemCacheEnabled,
                                                                                               int expectedCacheAddCount)
        {
            //Arrange
            string template = "just a string";

            byte[] bytes = Encoding.UTF8.GetBytes(template);

            Stream memoryStream = new MemoryStream(bytes);

            ILogger          logger          = CreateLogger();
            ICloudBlob       cloudBlob       = CreateBlob();
            IFileSystemCache fileSystemCache = CreateFileSystemCache();
            IExternalApiFileSystemCacheSettings cacheSettings = Substitute.For <IExternalApiFileSystemCacheSettings>();

            cacheSettings.IsEnabled.Returns(isFileSystemCacheEnabled);

            IBlobClient blobClient = CreateBlobClient();

            blobClient
            .BlobExistsAsync(blobName)
            .Returns(true);

            blobClient
            .GetBlobReferenceFromServerAsync(blobName)
            .Returns(cloudBlob);

            blobClient
            .DownloadToStreamAsync(cloudBlob)
            .Returns(memoryStream);

            ProviderFundingVersionService service = CreateProviderFundingVersionService(logger, blobClient, fileSystemCache, cacheSettings);

            //Act
            IActionResult result = await service.GetProviderFundingVersion(providerFundingVersion);

            //Assert
            result
            .Should()
            .BeOfType <ContentResult>();

            ContentResult contentResult = result as ContentResult;

            contentResult
            .ContentType
            .Should()
            .Be("application/json");

            contentResult
            .StatusCode
            .Should()
            .Be((int)HttpStatusCode.OK);

            contentResult
            .Content
            .Should()
            .Be(template);

            fileSystemCache
            .Received(expectedCacheAddCount)
            .Add(Arg.Is <ProviderFundingFileSystemCacheKey>(_ => _.Key == providerFundingVersion),
                 memoryStream,
                 CancellationToken.None);
        }
        public async Task GetProviderFundingVersionsBody_GivenReturnsFromFileSystemCacheAndSkipBlobClientFetch_ReturnsOK()
        {
            //Arrange
            string template = "just a string";

            byte[] bytes = Encoding.UTF8.GetBytes(template);

            Stream memoryStream = new MemoryStream(bytes);

            ILogger          logger          = CreateLogger();
            IFileSystemCache fileSystemCache = CreateFileSystemCache();
            IBlobClient      blobClient      = CreateBlobClient();

            fileSystemCache.Exists(Arg.Is <ProviderFundingFileSystemCacheKey>(
                                       _ => _.Key == providerFundingVersion))
            .Returns(true);

            fileSystemCache.Get(Arg.Is <ProviderFundingFileSystemCacheKey>(
                                    _ => _.Key == providerFundingVersion))
            .Returns(memoryStream);

            ProviderFundingVersionService service = CreateProviderFundingVersionService(logger, blobClient, fileSystemCache);

            //Act
            IActionResult result = await service.GetProviderFundingVersion(providerFundingVersion);

            //Assert
            result
            .Should()
            .BeOfType <ContentResult>();

            ContentResult contentResult = result as ContentResult;

            contentResult
            .ContentType
            .Should()
            .Be("application/json");

            contentResult
            .StatusCode
            .Should()
            .Be((int)HttpStatusCode.OK);

            contentResult
            .Content
            .Should()
            .Be(template);

            await blobClient
            .Received(0)
            .BlobExistsAsync(providerFundingVersion);

            await blobClient
            .Received(0)
            .GetAsync(Arg.Any <string>());

            fileSystemCache
            .Received(0)
            .Add(Arg.Is <ProviderFundingFileSystemCacheKey>(_ => _.Key == providerFundingVersion),
                 memoryStream,
                 CancellationToken.None);
        }