public async Task RenderOrderTemplateAsyncAsyncRendersFromTheTemplate()
        {
            // Arrange
            var metadata = new OrderTemplateMetadata
            {
                Sku              = "ABC",
                LineItemCount    = 4,
                AdditionalSheets = 3,
                AssetUrl         = "www.google.com"
            };

            var template = "Sku: @Model.Sku | LineItemCount: @Model.LineItemCount | TotalSheets: @Model.TotalSheets | AdditionalSheets: @Model.AdditionalSheets | AssetUrl: @Model.AssetUrl";
            var expected = template
                           .Replace("@Model.Sku", metadata.Sku)
                           .Replace("@Model.LineItemCount", metadata.LineItemCount.ToString())
                           .Replace("@Model.TotalSheets", metadata.TotalSheets.ToString())
                           .Replace("@Model.AdditionalSheets", metadata.AdditionalSheets.ToString())
                           .Replace("@Model.AssetUrl", metadata.AssetUrl);

            var mockStorage = new Mock <ISkuMetadataStorage>();

            mockStorage.Setup(storage => storage.TryRetrieveSkuMetadataAsync(It.IsAny <string>()))
            .ReturnsAsync((true, template));

            using (var processor = new SkuMetadataProcessor(new SkuMetadataProcessorConfiguration(), mockStorage.Object))
            {
                // Act
                var result = await processor.RenderOrderTemplateAsync(metadata);

                // Assert
                result.Should().NotBeNull("because a result should have been returned");
                result.Should().Be(expected, "because the template should have been randered");
            }
        }
        /// <summary>
        ///   Renders an order item template fragment for the given metadata.
        /// </summary>
        ///
        /// <param name="metadata">The metadata that describes the desired template rendering.</param>
        ///
        /// <returns>The rendered order line item fragment.</returns>
        ///
        public async Task <string> RenderOrderTemplateAsync(OrderTemplateMetadata metadata)
        {
            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            if (string.IsNullOrEmpty(metadata.Sku))
            {
                throw new ArgumentException("The SKU must be provided", nameof(metadata.Sku));
            }

            var storageResult = await this.metadataStorage.TryRetrieveSkuMetadataAsync(metadata.Sku);

            if (!storageResult.Found)
            {
                throw new MissingDependencyException("The sku metadata could not be located");
            }

            // NOTE: Razor Engine is unable to handle the same template name/key used with different templates
            //       so we use the hash to prevent it from throwing. It may leak a bit but it should be fine.
            //       Because this is all in process the string hash code should be good enough.
            var templateKey = $"{metadata.Sku}_{(storageResult.Metadata?.GetHashCode() ?? 0):X}";

            return(this.renderingEngine.RunCompile(storageResult.Metadata, templateKey, typeof(OrderTemplateMetadata), metadata));
        }
        public void RenderOrderTemplateAsyncValidatesTheSku(string sku)
        {
            var metadata = new OrderTemplateMetadata {
                Sku = sku
            };

            using (var processor = new SkuMetadataProcessor(new SkuMetadataProcessorConfiguration(), Mock.Of <ISkuMetadataStorage>()))
            {
                Action actionUnderTest = () => processor.RenderOrderTemplateAsync(null).GetAwaiter().GetResult();
                actionUnderTest.ShouldThrow <ArgumentException>("because the sku is required");
            }
        }
        public void RenderOrderTemplateAsyncAsyncThrowsForMissingStorageMetadata()
        {
            var mockStorage = new Mock <ISkuMetadataStorage>();
            var metadata    = new OrderTemplateMetadata {
                Sku = "ABC"
            };

            mockStorage.Setup(storage => storage.TryRetrieveSkuMetadataAsync(It.IsAny <string>()))
            .ReturnsAsync((false, null))
            .Verifiable("The SKU metadata should have been requested from storage");

            using (var processor = new SkuMetadataProcessor(new SkuMetadataProcessorConfiguration(), mockStorage.Object))
            {
                Action actionUnderTest = () => processor.RenderOrderTemplateAsync(metadata).GetAwaiter().GetResult();
                actionUnderTest.ShouldThrow <MissingDependencyException>("because the metadata in storage must be found");
            }

            mockStorage.VerifyAll();
        }