public async void HandlesConfigurationChanges()
        {
            // Arrange
            const string secretName   = "hello i'm a secret";
            const string firstSecret  = "secret1";
            const string secondSecret = "secret2";

            var arguments = new Dictionary <string, string>
            {
                { secretName, firstSecret }
            };

            ConfigurationProvider configProvider = new DictionaryConfigurationProvider(arguments);

            // Act
            var value1 = await configProvider.GetOrThrowAsync <string>(secretName);

            var value2 = await configProvider.GetOrDefaultAsync <string>(secretName);

            // Assert
            Assert.Equal(firstSecret, value1);
            Assert.Equal(value1, value2);

            // Arrange 2
            arguments[secretName] = secondSecret;

            // Act 2
            value1 = await configProvider.GetOrThrowAsync <string>(secretName);

            value2 = await configProvider.GetOrDefaultAsync <string>(secretName);

            // Assert 2
            Assert.Equal(secondSecret, value1);
            Assert.Equal(value1, value2);
        }
        public async void HandlesEmptyArgument(Type type)
        {
            // Arrange
            var defaultOfType = GetDefault(type);
            var memberOfType  = _typeToObject[type];

            var emptyValueKey = "this key has an empty value";

            object[] emptyValueKeyThrowArgs            = { emptyValueKey };
            object[] emptyValueKeyDefaultArgs          = { emptyValueKey, null };
            object[] emptyValueKeyDefaultSpecifiedArgs = { emptyValueKey, memberOfType };

            var arguments = new Dictionary <string, string>
            {
                { emptyValueKey, "" }
            };

            ConfigurationProvider configProvider = new DictionaryConfigurationProvider(arguments);

            var getOrThrowMethod   = typeof(IConfigurationProvider).GetMethod(nameof(IConfigurationProvider.GetOrThrowAsync)).MakeGenericMethod(type);
            var getOrDefaultMethod = typeof(IConfigurationProvider).GetMethod(nameof(IConfigurationProvider.GetOrDefaultAsync)).MakeGenericMethod(type);

            //// Assert

            // GetOrThrow
            await Assert.ThrowsAsync <ConfigurationNullOrEmptyException>(() => (Task)getOrThrowMethod.Invoke(configProvider, emptyValueKeyThrowArgs));

            // GetOrDefault
            Assert.Equal(defaultOfType, await(dynamic) getOrDefaultMethod.Invoke(configProvider, emptyValueKeyDefaultArgs));
            // GetOrDefault with default specified
            Assert.Equal(memberOfType, await(dynamic) getOrDefaultMethod.Invoke(configProvider, emptyValueKeyDefaultSpecifiedArgs));
        }
        public async void ThrowsForUnsupportedConversion()
        {
            // Arrange
            const string secretName = "hello i'm a secret";
            const string secretKey  = "fetch me from KeyVault pls";

            var arguments = new Dictionary <string, string>
            {
                { secretName, secretKey }
            };

            ConfigurationProvider configProvider = new DictionaryConfigurationProvider(arguments);

            // Assert
            await Assert.ThrowsAsync <NotSupportedException>(
                async() => await configProvider.GetOrThrowAsync <NoConversionFromStringToThisClass>(secretName));
        }