From 34899e15ad4ecf02b3392bbc01a12dba12c2d74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?DELAGE=20Rapha=C3=ABl?= <36408929+delager@users.noreply.github.com> Date: Thu, 30 Mar 2023 17:51:28 +0200 Subject: [PATCH] #1925 & #1928 Specific config handler and throw error if no CloudProvider (#1972) * #1925 & #1928 Specific config handler and throw error if no CloudProvider - Add AWS & Azure specific config handlers - Add AWSS3Storage configuration - Throw exception if CloudProvider undefined or unknown * #1925 - Missing TU for AWSS3StorageConnectionString in DevConfig * #1925 Null reference - Add ! for null reference possible --- .../ConfigHandler.cs | 1 + .../InvalidCloudProviderException.cs | 15 + .../Shared/Constants/ErrorTitles.cs | 6 + .../ConfigHandlerBase.cs | 1 + .../ConfigHandlerFactory.cs | 14 +- .../DevelopmentConfigHandler.cs | 11 +- .../ProductionAWSConfigHandler.cs | 92 ++++++ ...ler.cs => ProductionAzureConfigHandler.cs} | 21 +- .../Seeds/DeviceModelCommandSeeder.cs | 2 +- .../Seeds/DeviceModelPropertySeeder.cs | 2 +- .../Seeds/DeviceModelSeeder.cs | 2 +- .../Seeds/DeviceTagSeeder.cs | 2 +- .../Seeds/EdgeDeviceModelCommandSeeder.cs | 2 +- .../Seeds/EdgeDeviceModelSeeder.cs | 2 +- .../ConfigHandlerFactoryTest.cs | 59 +++- .../DevelopmentConfigHandlerTests.cs | 1 + .../ProductionAWSConfigHandlerTests.cs | 285 ++++++++++++++++++ ...s => ProductionAzureConfigHandlerTests.cs} | 58 ++-- 18 files changed, 532 insertions(+), 44 deletions(-) create mode 100644 src/AzureIoTHub.Portal.Domain/Exceptions/InvalidCloudProviderException.cs create mode 100644 src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs rename src/AzureIoTHub.Portal.Infrastructure/{ProductionConfigHandler.cs => ProductionAzureConfigHandler.cs} (87%) create mode 100644 src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAWSConfigHandlerTests.cs rename src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/{ProductionConfigHandlerTests.cs => ProductionAzureConfigHandlerTests.cs} (81%) diff --git a/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs b/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs index 957f41ed6..6b300e48c 100644 --- a/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs @@ -78,5 +78,6 @@ public abstract class ConfigHandler public abstract string AWSAccess { get; } public abstract string AWSAccessSecret { get; } public abstract string AWSRegion { get; } + public abstract string AWSS3StorageConnectionString { get; } } } diff --git a/src/AzureIoTHub.Portal.Domain/Exceptions/InvalidCloudProviderException.cs b/src/AzureIoTHub.Portal.Domain/Exceptions/InvalidCloudProviderException.cs new file mode 100644 index 000000000..218aa5b59 --- /dev/null +++ b/src/AzureIoTHub.Portal.Domain/Exceptions/InvalidCloudProviderException.cs @@ -0,0 +1,15 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Domain.Exceptions +{ + using System; + using AzureIoTHub.Portal.Domain.Shared.Constants; + + public class InvalidCloudProviderException : BaseException + { + public InvalidCloudProviderException(string detail, Exception? innerException = null) : base(ErrorTitles.InvalidCloudProvider, detail, innerException) + { + } + } +} diff --git a/src/AzureIoTHub.Portal.Domain/Shared/Constants/ErrorTitles.cs b/src/AzureIoTHub.Portal.Domain/Shared/Constants/ErrorTitles.cs index 15a35be17..00f3aa86d 100644 --- a/src/AzureIoTHub.Portal.Domain/Shared/Constants/ErrorTitles.cs +++ b/src/AzureIoTHub.Portal.Domain/Shared/Constants/ErrorTitles.cs @@ -10,5 +10,11 @@ public static class ErrorTitles public const string ResourceNotFound = "Resource Not Found"; public const string ResourceAlreadyExists = "Resource Already Exists"; + + public const string InvalidCloudProvider = "Invalid Cloud Provider"; + + public const string InvalidCloudProviderUndefined = "The CloudProvider configuration is undefined"; + + public const string InvalidCloudProviderIncorrect = "The CloudProvider configuration is incorrect"; } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs index fe173c382..425cb40a2 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs @@ -55,5 +55,6 @@ internal abstract class ConfigHandlerBase : ConfigHandler internal const string AWSAccessKey = "AWS:Access"; internal const string AWSAccessSecretKey = "AWS:AccessSecret"; internal const string AWSRegionKey = "AWS:Region"; + internal const string AWSS3StorageConnectionStringKey = "AWS:S3Storage:ConnectionString"; } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs index fc4c718b0..b45da02ed 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs @@ -5,6 +5,8 @@ namespace AzureIoTHub.Portal.Infrastructure { using System; using AzureIoTHub.Portal.Domain; + using AzureIoTHub.Portal.Domain.Exceptions; + using AzureIoTHub.Portal.Domain.Shared.Constants; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; @@ -15,9 +17,19 @@ public static ConfigHandler Create(IHostEnvironment env, IConfiguration config) ArgumentNullException.ThrowIfNull(env, nameof(env)); ArgumentNullException.ThrowIfNull(config, nameof(config)); + if (config[ConfigHandlerBase.CloudProviderKey] == null) + { + throw new InvalidCloudProviderException(ErrorTitles.InvalidCloudProviderUndefined); + } + if (env.IsProduction()) { - return new ProductionConfigHandler(config); + return config[ConfigHandlerBase.CloudProviderKey] switch + { + CloudProviders.AWS => new ProductionAWSConfigHandler(config), + CloudProviders.Azure => new ProductionAzureConfigHandler(config), + _ => throw new InvalidCloudProviderException(ErrorTitles.InvalidCloudProviderIncorrect), + }; } return new DevelopmentConfigHandler(config); diff --git a/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs index 2dd64285f..77db9f86e 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs @@ -80,12 +80,13 @@ internal DevelopmentConfigHandler(IConfiguration config) public override string MySQLConnectionString => this.config[MySQLConnectionStringKey]!; - public override string DbProvider => this.config.GetValue(DbProviderKey, DbProviders.PostgreSQL); + public override string DbProvider => this.config.GetValue(DbProviderKey, DbProviders.PostgreSQL)!; - public override string CloudProvider => this.config[CloudProviderKey]; + public override string CloudProvider => this.config[CloudProviderKey]!; - public override string AWSAccess => this.config[AWSAccessKey]; - public override string AWSAccessSecret => this.config[AWSAccessSecretKey]; - public override string AWSRegion => this.config[AWSRegionKey]; + public override string AWSAccess => this.config[AWSAccessKey]!; + public override string AWSAccessSecret => this.config[AWSAccessSecretKey]!; + public override string AWSRegion => this.config[AWSRegionKey]!; + public override string AWSS3StorageConnectionString => this.config[AWSS3StorageConnectionStringKey]!; } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs new file mode 100644 index 000000000..15382697a --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs @@ -0,0 +1,92 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Infrastructure +{ + using AzureIoTHub.Portal.Domain.Shared.Constants; + using Microsoft.Extensions.Configuration; + + internal class ProductionAWSConfigHandler : ConfigHandlerBase + { + private readonly IConfiguration config; + + internal ProductionAWSConfigHandler(IConfiguration config) + { + this.config = config; + } + + public override string PortalName => this.config[PortalNameKey]!; + + public override int SyncDatabaseJobRefreshIntervalInMinutes => this.config.GetValue(SyncDatabaseJobRefreshIntervalKey, 5); + + public override int MetricExporterRefreshIntervalInSeconds => this.config.GetValue(MetricExporterRefreshIntervalKey, 30); + + public override int MetricLoaderRefreshIntervalInMinutes => this.config.GetValue(MetricLoaderRefreshIntervalKey, 10); + + public override string IoTHubConnectionString => this.config[IoTHubConnectionStringKey]!; + + public override string IoTHubEventHubEndpoint => this.config.GetValue(IoTHubEventHubEndpointKey, string.Empty)!; + + public override string IoTHubEventHubConsumerGroup => this.config.GetValue(IoTHubEventHubConsumerGroupKey, "iothub-portal")!; + + public override string DPSConnectionString => this.config[DPSConnectionStringKey]!; + + public override string DPSEndpoint => this.config[DPSServiceEndpointKey]!; + + public override string DPSScopeID => this.config[DPSIDScopeKey]!; + + public override string StorageAccountConnectionString => throw new NotImplementedException(); + + public override int StorageAccountDeviceModelImageMaxAge => throw new NotImplementedException(); + + public override bool UseSecurityHeaders => this.config.GetValue(UseSecurityHeadersKey, true); + + public override string OIDCScope => this.config[OIDCScopeKey]!; + + public override string OIDCAuthority => this.config[OIDCAuthorityKey]!; + + public override string OIDCMetadataUrl => this.config[OIDCMetadataUrlKey]!; + + public override string OIDCClientId => this.config[OIDCClientIdKey]!; + + public override string OIDCApiClientId => this.config[OIDCApiClientIdKey]!; + + public override bool OIDCValidateIssuer => this.config.GetValue(OIDCValidateIssuerKey, true); + + public override bool OIDCValidateAudience => this.config.GetValue(OIDCValidateAudienceKey, true); + + public override bool OIDCValidateLifetime => this.config.GetValue(OIDCValidateLifetimeKey, true); + + public override bool OIDCValidateIssuerSigningKey => this.config.GetValue(OIDCValidateIssuerSigningKeyKey, true); + + public override bool OIDCValidateActor => this.config.GetValue(OIDCValidateActorKey, false); + + public override bool OIDCValidateTokenReplay => this.config.GetValue(OIDCValidateTokenReplayKey, false); + + public override bool IsLoRaEnabled => bool.Parse(this.config[IsLoRaFeatureEnabledKey] ?? "true"); + + public override string LoRaKeyManagementUrl => this.config[LoRaKeyManagementUrlKey]!; + + public override string LoRaKeyManagementCode => this.config[LoRaKeyManagementCodeKey]!; + + public override string LoRaKeyManagementApiVersion => this.config[LoRaKeyManagementApiVersionKey]!; + + public override bool IdeasEnabled => this.config.GetValue(IdeasEnabledKey, false); + public override string IdeasUrl => this.config.GetValue(IdeasUrlKey, string.Empty)!; + public override string IdeasAuthenticationHeader => this.config.GetValue(IdeasAuthenticationHeaderKey, "Ocp-Apim-Subscription-Key")!; + public override string IdeasAuthenticationToken => this.config.GetValue(IdeasAuthenticationTokenKey, string.Empty)!; + + public override string PostgreSQLConnectionString => this.config[PostgreSQLConnectionStringKey]!; + + public override string MySQLConnectionString => this.config[MySQLConnectionStringKey]!; + + public override string DbProvider => this.config.GetValue(DbProviderKey, DbProviders.PostgreSQL)!; + + public override string CloudProvider => this.config[CloudProviderKey]!; + + public override string AWSAccess => this.config[AWSAccessKey]!; + public override string AWSAccessSecret => this.config[AWSAccessSecretKey]!; + public override string AWSRegion => this.config[AWSRegionKey]!; + public override string AWSS3StorageConnectionString => this.config[AWSS3StorageConnectionStringKey]!; + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs similarity index 87% rename from src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs rename to src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs index ba04bd317..48b5ed60e 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ProductionConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs @@ -6,11 +6,11 @@ namespace AzureIoTHub.Portal.Infrastructure using AzureIoTHub.Portal.Domain.Shared.Constants; using Microsoft.Extensions.Configuration; - internal class ProductionConfigHandler : ConfigHandlerBase + internal class ProductionAzureConfigHandler : ConfigHandlerBase { private readonly IConfiguration config; - internal ProductionConfigHandler(IConfiguration config) + internal ProductionAzureConfigHandler(IConfiguration config) { this.config = config; } @@ -78,14 +78,17 @@ internal ProductionConfigHandler(IConfiguration config) public override string LoRaKeyManagementApiVersion => this.config[LoRaKeyManagementApiVersionKey]!; public override bool IdeasEnabled => this.config.GetValue(IdeasEnabledKey, false); - public override string IdeasUrl => this.config.GetValue(IdeasUrlKey, string.Empty); - public override string IdeasAuthenticationHeader => this.config.GetValue(IdeasAuthenticationHeaderKey, "Ocp-Apim-Subscription-Key"); - public override string IdeasAuthenticationToken => this.config.GetValue(IdeasAuthenticationTokenKey, string.Empty); + public override string IdeasUrl => this.config.GetValue(IdeasUrlKey, string.Empty)!; + public override string IdeasAuthenticationHeader => this.config.GetValue(IdeasAuthenticationHeaderKey, "Ocp-Apim-Subscription-Key")!; + public override string IdeasAuthenticationToken => this.config.GetValue(IdeasAuthenticationTokenKey, string.Empty)!; - public override string CloudProvider => this.config[CloudProviderKey]; + public override string CloudProvider => this.config[CloudProviderKey]!; - public override string AWSAccess => this.config[AWSAccessKey]; - public override string AWSAccessSecret => this.config[AWSAccessSecretKey]; - public override string AWSRegion => this.config[AWSRegionKey]; + public override string AWSAccess => throw new NotImplementedException(); + + public override string AWSAccessSecret => throw new NotImplementedException(); + + public override string AWSRegion => throw new NotImplementedException(); + public override string AWSS3StorageConnectionString => throw new NotImplementedException(); } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs index c3535277f..862fe52a4 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelCommandSeeder.cs @@ -36,7 +36,7 @@ public static async Task MigrateDeviceModelCommands(this PortalDbContext ctx, Co }); #pragma warning restore CS8629 // Nullable value type may be null. - if (config is ProductionConfigHandler) + if (config is ProductionAzureConfigHandler) { _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelPropertySeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelPropertySeeder.cs index b1f3310b7..264c06079 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelPropertySeeder.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelPropertySeeder.cs @@ -36,7 +36,7 @@ public static async Task MigrateDeviceModelProperties(this PortalDbContext ctx, }); #pragma warning restore CS8629 // Nullable value type may be null. - if (config is ProductionConfigHandler) + if (config is ProductionAzureConfigHandler) { _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelSeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelSeeder.cs index ce9be137d..6f77c5abe 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelSeeder.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceModelSeeder.cs @@ -44,7 +44,7 @@ public static async Task MigrateDeviceModels(this PortalDbContext ctx, ConfigHan }); #pragma warning restore CS8629 // Nullable value type may be null. - if (config is ProductionConfigHandler) + if (config is ProductionAzureConfigHandler) { _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceTagSeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceTagSeeder.cs index 36f87f2e6..68842a0b6 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceTagSeeder.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/DeviceTagSeeder.cs @@ -33,7 +33,7 @@ public static async Task MigrateDeviceTags(this PortalDbContext ctx, ConfigHandl }); #pragma warning restore CS8629 // Nullable value type may be null. - if (config is ProductionConfigHandler) + if (config is ProductionAzureConfigHandler) { _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelCommandSeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelCommandSeeder.cs index 25dd8a827..6994d1c73 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelCommandSeeder.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelCommandSeeder.cs @@ -33,7 +33,7 @@ public static async Task MigrateEdgeDeviceModelCommands(this PortalDbContext ctx }); #pragma warning restore CS8629 // Nullable value type may be null. - if (config is ProductionConfigHandler) + if (config is ProductionAzureConfigHandler) { _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelSeeder.cs b/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelSeeder.cs index 700ca1d51..c86a6fa07 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelSeeder.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Seeds/EdgeDeviceModelSeeder.cs @@ -32,7 +32,7 @@ public static async Task MigrateEdgeDeviceModels(this PortalDbContext ctx, Confi }); #pragma warning restore CS8629 // Nullable value type may be null. - if (config is ProductionConfigHandler) + if (config is ProductionAzureConfigHandler) { _ = await table.DeleteEntityAsync(item.PartitionKey, item.RowKey); } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ConfigHandlerFactoryTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ConfigHandlerFactoryTest.cs index cec598f97..fbeec0b99 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ConfigHandlerFactoryTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ConfigHandlerFactoryTest.cs @@ -3,7 +3,10 @@ namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure { + using AzureIoTHub.Portal.Domain.Exceptions; + using AzureIoTHub.Portal.Domain.Shared.Constants; using AzureIoTHub.Portal.Infrastructure; + using FluentAssertions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Moq; @@ -31,6 +34,8 @@ public void WhenUsingDevEnvironmentShouldReturnDevelopmentConfigHandler() // Arrange _ = this.mockHostEnvironment.Setup(c => c.EnvironmentName) .Returns(Environments.Development); + _ = this.mockConfiguration.Setup(cnf => cnf[ConfigHandlerBase.CloudProviderKey]) + .Returns(CloudProviders.Azure); // Act var result = ConfigHandlerFactory.Create(this.mockHostEnvironment.Object, this.mockConfiguration.Object); @@ -41,17 +46,67 @@ public void WhenUsingDevEnvironmentShouldReturnDevelopmentConfigHandler() [Test] - public void WhenUsingProdEnvironmentShouldReturnProductionConfigHandler() + public void WhenUsingProdAzureEnvironmentShouldReturnProductionAzureConfigHandler() { // Arrange _ = this.mockHostEnvironment.Setup(c => c.EnvironmentName) .Returns(Environments.Production); + _ = this.mockConfiguration.Setup(cnf => cnf[ConfigHandlerBase.CloudProviderKey]) + .Returns(CloudProviders.Azure); // Act var result = ConfigHandlerFactory.Create(this.mockHostEnvironment.Object, this.mockConfiguration.Object); // Assert - Assert.IsAssignableFrom(result); + Assert.IsAssignableFrom(result); + } + + [Test] + public void WhenUsingProdAWSEnvironmentShouldReturnProductionAWSConfigHandler() + { + // Arrange + _ = this.mockHostEnvironment.Setup(c => c.EnvironmentName) + .Returns(Environments.Production); + _ = this.mockConfiguration.Setup(cnf => cnf[ConfigHandlerBase.CloudProviderKey]) + .Returns(CloudProviders.AWS); + + // Act + var result = ConfigHandlerFactory.Create(this.mockHostEnvironment.Object, this.mockConfiguration.Object); + + // Assert + Assert.IsAssignableFrom(result); + } + + [Test] + public void WhenNoConfigCloudProviderShouldThrowInvalidCloudProviderException() + { + // Arrange + _ = this.mockHostEnvironment.Setup(c => c.EnvironmentName) + .Returns(Environments.Production); + _ = this.mockConfiguration.Setup(cnf => cnf[ConfigHandlerBase.CloudProviderKey]) + .Returns((string)null); + + // Act + var result = () => ConfigHandlerFactory.Create(this.mockHostEnvironment.Object, this.mockConfiguration.Object); + + // Assert + _ = result.Should().Throw().WithMessage(ErrorTitles.InvalidCloudProviderUndefined); + } + + [Test] + public void WhenWrongCloudProviderShouldThrowInvalidCloudProviderException() + { + // Arrange + _ = this.mockHostEnvironment.Setup(c => c.EnvironmentName) + .Returns(Environments.Production); + _ = this.mockConfiguration.Setup(cnf => cnf[ConfigHandlerBase.CloudProviderKey]) + .Returns("Test"); + + // Act + var result = () => ConfigHandlerFactory.Create(this.mockHostEnvironment.Object, this.mockConfiguration.Object); + + // Assert + _ = result.Should().Throw().WithMessage(ErrorTitles.InvalidCloudProviderIncorrect); } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/DevelopmentConfigHandlerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/DevelopmentConfigHandlerTests.cs index bb62f55ce..d7dc11942 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/DevelopmentConfigHandlerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/DevelopmentConfigHandlerTests.cs @@ -51,6 +51,7 @@ private DevelopmentConfigHandler CreateDevelopmentConfigHandler() [TestCase(ConfigHandlerBase.AWSAccessKey, nameof(ConfigHandlerBase.AWSAccess))] [TestCase(ConfigHandlerBase.AWSAccessSecretKey, nameof(ConfigHandlerBase.AWSAccessSecret))] [TestCase(ConfigHandlerBase.AWSRegionKey, nameof(ConfigHandlerBase.AWSRegion))] + [TestCase(ConfigHandlerBase.AWSS3StorageConnectionStringKey, nameof(ConfigHandlerBase.AWSS3StorageConnectionString))] [TestCase(ConfigHandlerBase.CloudProviderKey, nameof(ConfigHandlerBase.CloudProvider))] public void SettingsShouldGetValueFromAppSettings(string configKey, string configPropertyName) { diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAWSConfigHandlerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAWSConfigHandlerTests.cs new file mode 100644 index 000000000..567188f06 --- /dev/null +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAWSConfigHandlerTests.cs @@ -0,0 +1,285 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure +{ + using System; + using System.Globalization; + using System.Reflection; + using AzureIoTHub.Portal.Domain.Shared.Constants; + using AzureIoTHub.Portal.Infrastructure; + using FluentAssertions; + using Microsoft.Extensions.Configuration; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class ProductionAWSConfigHandlerTests + { + private MockRepository mockRepository; + + private Mock mockConfiguration; + + [SetUp] + public void SetUp() + { + this.mockRepository = new MockRepository(MockBehavior.Strict); + + this.mockConfiguration = this.mockRepository.Create(); + } + + private ProductionAWSConfigHandler CreateProductionAWSConfigHandler() + { + return new ProductionAWSConfigHandler(this.mockConfiguration.Object); + } + + [TestCase(ConfigHandlerBase.PortalNameKey, nameof(ConfigHandlerBase.PortalName))] + [TestCase(ConfigHandlerBase.DPSServiceEndpointKey, nameof(ConfigHandlerBase.DPSEndpoint))] + [TestCase(ConfigHandlerBase.DPSIDScopeKey, nameof(ConfigHandlerBase.DPSScopeID))] + [TestCase(ConfigHandlerBase.OIDCScopeKey, nameof(ConfigHandlerBase.OIDCScope))] + [TestCase(ConfigHandlerBase.OIDCAuthorityKey, nameof(ConfigHandlerBase.OIDCAuthority))] + [TestCase(ConfigHandlerBase.OIDCMetadataUrlKey, nameof(ConfigHandlerBase.OIDCMetadataUrl))] + [TestCase(ConfigHandlerBase.OIDCClientIdKey, nameof(ConfigHandlerBase.OIDCClientId))] + [TestCase(ConfigHandlerBase.OIDCApiClientIdKey, nameof(ConfigHandlerBase.OIDCApiClientId))] + [TestCase(ConfigHandlerBase.LoRaKeyManagementUrlKey, nameof(ConfigHandlerBase.LoRaKeyManagementUrl))] + [TestCase(ConfigHandlerBase.LoRaKeyManagementCodeKey, nameof(ConfigHandlerBase.LoRaKeyManagementCode))] + [TestCase(ConfigHandlerBase.LoRaKeyManagementApiVersionKey, nameof(ConfigHandlerBase.LoRaKeyManagementApiVersion))] + [TestCase(ConfigHandlerBase.IoTHubConnectionStringKey, nameof(ConfigHandlerBase.IoTHubConnectionString))] + [TestCase(ConfigHandlerBase.DPSConnectionStringKey, nameof(ConfigHandlerBase.DPSConnectionString))] + [TestCase(ConfigHandlerBase.PostgreSQLConnectionStringKey, nameof(ConfigHandlerBase.PostgreSQLConnectionString))] + [TestCase(ConfigHandlerBase.MySQLConnectionStringKey, nameof(ConfigHandlerBase.MySQLConnectionString))] + [TestCase(ConfigHandlerBase.AWSAccessKey, nameof(ConfigHandlerBase.AWSAccess))] + [TestCase(ConfigHandlerBase.AWSAccessSecretKey, nameof(ConfigHandlerBase.AWSAccessSecret))] + [TestCase(ConfigHandlerBase.AWSRegionKey, nameof(ConfigHandlerBase.AWSRegion))] + [TestCase(ConfigHandlerBase.AWSS3StorageConnectionStringKey, nameof(ConfigHandlerBase.AWSS3StorageConnectionString))] + [TestCase(ConfigHandlerBase.CloudProviderKey, nameof(ConfigHandlerBase.CloudProvider))] + public void SettingsShouldGetValueFromAppSettings(string configKey, string configPropertyName) + { + // Arrange + var expected = Guid.NewGuid().ToString(); + var configHandler = CreateProductionAWSConfigHandler(); + + _ = this.mockConfiguration.SetupGet(c => c[It.Is(x => x == configKey)]) + .Returns(expected); + + // Act + var result = configHandler + .GetType() + .GetProperty(configPropertyName) + .GetValue(configHandler, null); + + // Assert + Assert.AreEqual(expected, result); + this.mockRepository.VerifyAll(); + } + + [TestCase(nameof(ConfigHandlerBase.StorageAccountConnectionString))] + [TestCase(nameof(ConfigHandlerBase.StorageAccountDeviceModelImageMaxAge))] + public void SettingsShouldThrowError(string configPropertyName) + { + // Arrange + var productionConfigHandler = CreateProductionAWSConfigHandler(); + + // Act + var result = () => productionConfigHandler.GetType().GetProperty(configPropertyName).GetValue(productionConfigHandler, null); + + // Assert + _ = result.Should().Throw(); + + this.mockRepository.VerifyAll(); + } + + [TestCase(ConfigHandlerBase.OIDCValidateAudienceKey, nameof(ConfigHandlerBase.OIDCValidateAudience))] + [TestCase(ConfigHandlerBase.OIDCValidateIssuerKey, nameof(ConfigHandlerBase.OIDCValidateIssuer))] + [TestCase(ConfigHandlerBase.OIDCValidateIssuerSigningKeyKey, nameof(ConfigHandlerBase.OIDCValidateIssuerSigningKey))] + [TestCase(ConfigHandlerBase.OIDCValidateLifetimeKey, nameof(ConfigHandlerBase.OIDCValidateLifetime))] + [TestCase(ConfigHandlerBase.UseSecurityHeadersKey, nameof(ConfigHandlerBase.UseSecurityHeaders))] + public void SecuritySwitchesShouldBeEnabledByDefault(string configKey, string configPropertyName) + { + // Arrange + var configHandler = CreateProductionAWSConfigHandler(); + var mockConfigurationSection = this.mockRepository.Create(); + + _ = mockConfigurationSection.SetupGet(c => c.Value) + .Returns((string)null); + + _ = mockConfigurationSection.SetupGet(c => c.Path) + .Returns(string.Empty); + + _ = this.mockConfiguration.Setup(c => c.GetSection(configKey)) + .Returns(mockConfigurationSection.Object); + + // Act + var result = (bool)configHandler + .GetType() + .GetProperty(configPropertyName) + .GetValue(configHandler, null); + + // Assert + Assert.IsTrue(result); + } + + [TestCase(ConfigHandlerBase.OIDCValidateActorKey, nameof(ConfigHandlerBase.OIDCValidateActor))] + [TestCase(ConfigHandlerBase.OIDCValidateTokenReplayKey, nameof(ConfigHandlerBase.OIDCValidateTokenReplay))] + public void SecuritySwitchesShouldBeDisabledByDefault(string configKey, string configPropertyName) + { + // Arrange + var configHandler = CreateProductionAWSConfigHandler(); + var mockConfigurationSection = this.mockRepository.Create(); + + _ = mockConfigurationSection.SetupGet(c => c.Value) + .Returns((string)null); + + _ = mockConfigurationSection.SetupGet(c => c.Path) + .Returns(string.Empty); + + _ = this.mockConfiguration.Setup(c => c.GetSection(configKey)) + .Returns(mockConfigurationSection.Object); + + // Act + var result = (bool)configHandler + .GetType() + .GetProperty(configPropertyName) + .GetValue(configHandler, null); + + // Assert + Assert.IsFalse(result); + } + + [TestCase(ConfigHandlerBase.IsLoRaFeatureEnabledKey, nameof(ConfigHandlerBase.IsLoRaEnabled))] + public void SettingsShouldGetBoolFromAppSettings(string configKey, string configPropertyName) + { + // Arrange + var expected = false; + var productionConfigHandler = CreateProductionAWSConfigHandler(); + + _ = this.mockConfiguration.SetupGet(c => c[It.Is(x => x == configKey)]) + .Returns(Convert.ToString(expected, CultureInfo.InvariantCulture)); + + // Act + var result = productionConfigHandler + .GetType() + .GetProperty(configPropertyName) + .GetValue(productionConfigHandler, null); + + // Assert + Assert.AreEqual(expected, result); + + // Arrange + expected = true; + + _ = this.mockConfiguration.SetupGet(c => c[It.Is(x => x == configKey)]) + .Returns(Convert.ToString(expected, CultureInfo.InvariantCulture)); + + // Act + result = productionConfigHandler + .GetType() + .GetProperty(configPropertyName) + .GetValue(productionConfigHandler, null); + + // Assert + Assert.AreEqual(expected, result); + this.mockRepository.VerifyAll(); + } + + [Test] + public void SyncDatabaseJobRefreshIntervalInMinutesConfigMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.SyncDatabaseJobRefreshIntervalInMinutes.Should().Be(5); + } + + [Test] + public void MetricExporterRefreshIntervalInSecondsConfigMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.MetricExporterRefreshIntervalInSeconds.Should().Be(30); + } + + [Test] + public void MetricLoaderRefreshIntervalInMinutesConfigMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.MetricLoaderRefreshIntervalInMinutes.Should().Be(10); + } + + [Test] + public void IdeasEnabledMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.IdeasEnabled.Should().BeFalse(); + } + + [Test] + public void IdeasUrlMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.IdeasUrl.Should().BeEmpty(); + } + + [Test] + public void IdeasAuthenticationHeaderMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.IdeasAuthenticationHeader.Should().Be("Ocp-Apim-Subscription-Key"); + } + + [Test] + public void IdeasAuthenticationTokenMustHaveDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.IdeasAuthenticationToken.Should().BeEmpty(); + } + + [Test] + public void IoTHubEventHubEndpoint_GetDefaultValue_ReturnsEmpty() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.IoTHubEventHubEndpoint.Should().BeEmpty(); + } + + [Test] + public void IoTHubEventHubConsumerGroup_GetDefaultValue_ReturnsExpectedDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.IoTHubEventHubConsumerGroup.Should().Be("iothub-portal"); + } + + [Test] + public void DbProviderKeyShouldBeExpectedDefaultValue() + { + // Arrange + var productionAWSConfigHandler = new ProductionAWSConfigHandler(new ConfigurationManager()); + + // Assert + _ = productionAWSConfigHandler.DbProvider.Should().Be(DbProviders.PostgreSQL); + } + } +} diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionConfigHandlerTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAzureConfigHandlerTests.cs similarity index 81% rename from src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionConfigHandlerTests.cs rename to src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAzureConfigHandlerTests.cs index 217020387..047aa1435 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionConfigHandlerTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/ProductionAzureConfigHandlerTests.cs @@ -11,9 +11,10 @@ namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure using NUnit.Framework; using AzureIoTHub.Portal.Infrastructure; using AzureIoTHub.Portal.Domain.Shared.Constants; + using System.Reflection; [TestFixture] - public class ProductionConfigHandlerTests + public class ProductionAzureConfigHandlerTests { private MockRepository mockRepository; @@ -27,9 +28,9 @@ public void SetUp() this.mockConfiguration = this.mockRepository.Create(); } - private ProductionConfigHandler CreateProductionConfigHandler() + private ProductionAzureConfigHandler CreateProductionAzureConfigHandler() { - return new ProductionConfigHandler(this.mockConfiguration.Object); + return new ProductionAzureConfigHandler(this.mockConfiguration.Object); } [TestCase(ConfigHandlerBase.IoTHubConnectionStringKey, nameof(ConfigHandlerBase.IoTHubConnectionString))] @@ -43,7 +44,7 @@ public void SecretsShouldGetValueFromConnectionStrings(string configKey, string { // Arrange var expected = Guid.NewGuid().ToString(); - var productionConfigHandler = CreateProductionConfigHandler(); + var productionConfigHandler = CreateProductionAzureConfigHandler(); var mockConfigurationSection = this.mockRepository.Create(); _ = this.mockConfiguration.Setup(c => c.GetSection(It.Is(x => x == "ConnectionStrings"))) @@ -73,15 +74,12 @@ public void SecretsShouldGetValueFromConnectionStrings(string configKey, string [TestCase(ConfigHandlerBase.OIDCApiClientIdKey, nameof(ConfigHandlerBase.OIDCApiClientId))] [TestCase(ConfigHandlerBase.LoRaKeyManagementUrlKey, nameof(ConfigHandlerBase.LoRaKeyManagementUrl))] [TestCase(ConfigHandlerBase.LoRaKeyManagementApiVersionKey, nameof(ConfigHandlerBase.LoRaKeyManagementApiVersion))] - [TestCase(ConfigHandlerBase.AWSAccessKey, nameof(ConfigHandlerBase.AWSAccess))] - [TestCase(ConfigHandlerBase.AWSAccessSecretKey, nameof(ConfigHandlerBase.AWSAccessSecret))] - [TestCase(ConfigHandlerBase.AWSRegionKey, nameof(ConfigHandlerBase.AWSRegion))] [TestCase(ConfigHandlerBase.CloudProviderKey, nameof(ConfigHandlerBase.CloudProvider))] public void SettingsShouldGetValueFromAppSettings(string configKey, string configPropertyName) { // Arrange var expected = Guid.NewGuid().ToString(); - var productionConfigHandler = CreateProductionConfigHandler(); + var productionConfigHandler = CreateProductionAzureConfigHandler(); _ = this.mockConfiguration.SetupGet(c => c[It.Is(x => x == configKey)]) .Returns(expected); @@ -97,6 +95,24 @@ public void SettingsShouldGetValueFromAppSettings(string configKey, string confi this.mockRepository.VerifyAll(); } + [TestCase(nameof(ConfigHandlerBase.AWSAccess))] + [TestCase(nameof(ConfigHandlerBase.AWSAccessSecret))] + [TestCase(nameof(ConfigHandlerBase.AWSRegion))] + [TestCase(nameof(ConfigHandlerBase.AWSS3StorageConnectionString))] + public void SettingsShouldThrowError(string configPropertyName) + { + // Arrange + var productionConfigHandler = CreateProductionAzureConfigHandler(); + + // Act + var result = () => productionConfigHandler.GetType().GetProperty(configPropertyName).GetValue(productionConfigHandler, null); + + // Assert + _ = result.Should().Throw(); + + this.mockRepository.VerifyAll(); + } + [TestCase(ConfigHandlerBase.OIDCValidateAudienceKey, nameof(ConfigHandlerBase.OIDCValidateAudience))] [TestCase(ConfigHandlerBase.OIDCValidateIssuerKey, nameof(ConfigHandlerBase.OIDCValidateIssuer))] [TestCase(ConfigHandlerBase.OIDCValidateIssuerSigningKeyKey, nameof(ConfigHandlerBase.OIDCValidateIssuerSigningKey))] @@ -105,7 +121,7 @@ public void SettingsShouldGetValueFromAppSettings(string configKey, string confi public void SecuritySwitchesShouldBeEnabledByDefault(string configKey, string configPropertyName) { // Arrange - var configHandler = CreateProductionConfigHandler(); + var configHandler = CreateProductionAzureConfigHandler(); var mockConfigurationSection = this.mockRepository.Create(); _ = mockConfigurationSection.SetupGet(c => c.Value) @@ -132,7 +148,7 @@ public void SecuritySwitchesShouldBeEnabledByDefault(string configKey, string co public void SecuritySwitchesShouldBeDisabledByDefault(string configKey, string configPropertyName) { // Arrange - var configHandler = CreateProductionConfigHandler(); + var configHandler = CreateProductionAzureConfigHandler(); var mockConfigurationSection = this.mockRepository.Create(); _ = mockConfigurationSection.SetupGet(c => c.Value) @@ -159,7 +175,7 @@ public void SettingsShouldGetBoolFromAppSettings(string configKey, string config { // Arrange var expected = false; - var productionConfigHandler = CreateProductionConfigHandler(); + var productionConfigHandler = CreateProductionAzureConfigHandler(); _ = this.mockConfiguration.SetupGet(c => c[It.Is(x => x == configKey)]) .Returns(Convert.ToString(expected, CultureInfo.InvariantCulture)); @@ -194,7 +210,7 @@ public void SettingsShouldGetBoolFromAppSettings(string configKey, string config public void SyncDatabaseJobRefreshIntervalInMinutesConfigMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.SyncDatabaseJobRefreshIntervalInMinutes.Should().Be(5); @@ -204,7 +220,7 @@ public void SyncDatabaseJobRefreshIntervalInMinutesConfigMustHaveDefaultValue() public void MetricExporterRefreshIntervalInSecondsConfigMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.MetricExporterRefreshIntervalInSeconds.Should().Be(30); @@ -214,7 +230,7 @@ public void MetricExporterRefreshIntervalInSecondsConfigMustHaveDefaultValue() public void MetricLoaderRefreshIntervalInMinutesConfigMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.MetricLoaderRefreshIntervalInMinutes.Should().Be(10); @@ -224,7 +240,7 @@ public void MetricLoaderRefreshIntervalInMinutesConfigMustHaveDefaultValue() public void IdeasEnabledMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.IdeasEnabled.Should().BeFalse(); @@ -234,7 +250,7 @@ public void IdeasEnabledMustHaveDefaultValue() public void IdeasUrlMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.IdeasUrl.Should().BeEmpty(); @@ -244,7 +260,7 @@ public void IdeasUrlMustHaveDefaultValue() public void IdeasAuthenticationHeaderMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.IdeasAuthenticationHeader.Should().Be("Ocp-Apim-Subscription-Key"); @@ -254,7 +270,7 @@ public void IdeasAuthenticationHeaderMustHaveDefaultValue() public void IdeasAuthenticationTokenMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.IdeasAuthenticationToken.Should().BeEmpty(); @@ -264,7 +280,7 @@ public void IdeasAuthenticationTokenMustHaveDefaultValue() public void StorageAccountDeviceModelImageMaxAgeMustHaveDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.StorageAccountDeviceModelImageMaxAge.Should().Be(86400); @@ -274,7 +290,7 @@ public void StorageAccountDeviceModelImageMaxAgeMustHaveDefaultValue() public void IoTHubEventHubConsumerGroup_GetDefaultValue_ReturnsExpectedDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.IoTHubEventHubConsumerGroup.Should().Be("iothub-portal"); @@ -284,7 +300,7 @@ public void IoTHubEventHubConsumerGroup_GetDefaultValue_ReturnsExpectedDefaultVa public void DbProviderKeyShouldBeExpectedDefaultValue() { // Arrange - var productionConfigHandler = new ProductionConfigHandler(new ConfigurationManager()); + var productionConfigHandler = new ProductionAzureConfigHandler(new ConfigurationManager()); // Assert _ = productionConfigHandler.DbProvider.Should().Be(DbProviders.PostgreSQL);