762 lines
36 KiB
C#
Raw Normal View History

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Config
{
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Linq;
using System.Data.Entity.TestHelpers;
using Moq;
using SimpleModel;
using Xunit;
public class DbConfigurationManagerTests : TestBase
{
public class Instance : TestBase
{
[Fact]
public void Instance_returns_the_Singleton_instance()
{
Assert.NotNull(DbConfigurationManager.Instance);
Assert.Same(DbConfigurationManager.Instance, DbConfigurationManager.Instance);
}
}
public class GetConfiguration : TestBase
{
[Fact]
public void GetConfiguration_returns_the_configuration_at_the_top_of_the_stack_if_overriding_configurations_have_been_pushed()
{
var manager = CreateManager();
var mockInternalConfiguration = new Mock<InternalConfiguration>
{
CallBase = true
};
var mockDbConfiguration = new Mock<DbConfiguration>();
mockDbConfiguration.Setup(m => m.InternalConfiguration).Returns(mockInternalConfiguration.Object);
mockInternalConfiguration.Setup(m => m.Owner).Returns(mockDbConfiguration.Object);
var configuration = mockInternalConfiguration.Object;
manager.SetConfiguration(configuration);
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
var pushed1 = manager.GetConfiguration();
Assert.NotSame(configuration, pushed1);
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
var pushed2 = manager.GetConfiguration();
Assert.NotSame(pushed1, pushed2);
Assert.NotSame(configuration, pushed2);
}
[Fact]
public void GetConfiguration_returns_the_previously_set_configuration()
{
var manager = CreateManager();
var mockInternalConfiguration = CreateMockInternalConfiguration();
manager.SetConfiguration(mockInternalConfiguration.Object);
Assert.Same(mockInternalConfiguration.Object, manager.GetConfiguration());
}
[Fact]
public void GetConfiguration_sets_and_returns_a_new_configuration_if_none_was_previously_set()
{
var manager = CreateManager();
var configuration = manager.GetConfiguration();
Assert.NotNull(configuration);
Assert.Same(configuration, manager.GetConfiguration());
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void GetConfiguration_for_default_value_can_be_called_from_multiple_threads_concurrently()
{
ConfigurationThreadTest(m => { }, m => { });
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void GetConfiguration_for_pushed_config_can_be_called_from_multiple_threads_concurrently()
{
ConfigurationThreadTest(m => m.PushConfiguration(AppConfig.DefaultInstance, typeof(SimpleModelContext)), m => { });
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void GetConfiguration_for_pushed_and_popped_config_can_be_called_from_multiple_threads_concurrently()
{
ConfigurationThreadTest(
m =>
{
m.PushConfiguration(AppConfig.DefaultInstance, typeof(SimpleModelContext));
m.PopConfiguration(AppConfig.DefaultInstance);
},
m => { });
}
}
public class SetConfiguration : TestBase
{
[Fact]
public void SetConfiguration_sets_and_locks_the_configuration_if_none_was_previously_set_and_config_file_has_none()
{
var manager = CreateManager();
var mockInternalConfiguration = CreateMockInternalConfiguration();
manager.SetConfiguration(mockInternalConfiguration.Object);
Assert.Same(mockInternalConfiguration.Object, manager.GetConfiguration());
mockInternalConfiguration.Verify(m => m.Lock());
}
[Fact]
public void The_same_type_of_configuration_can_be_set_multiple_times()
{
var manager = CreateManager();
var mockInternalConfiguration1 = CreateMockInternalConfiguration();
var mockInternalConfiguration2 = CreateMockInternalConfiguration();
manager.SetConfiguration(mockInternalConfiguration1.Object);
manager.SetConfiguration(mockInternalConfiguration2.Object);
Assert.Same(mockInternalConfiguration1.Object, manager.GetConfiguration());
}
[Fact]
public void SetConfiguration_discards_the_given_configuration_and_uses_the_configuration_from_the_config_file_if_it_exists()
{
var mockLoadedConfig = CreateMockInternalConfiguration();
var mockLoader = new Mock<DbConfigurationLoader>();
mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny<AppConfig>())).Returns(true);
mockLoader.Setup(m => m.TryLoadFromConfig(It.IsAny<AppConfig>())).Returns(mockLoadedConfig.Object);
var manager = CreateManager(mockLoader);
var mockConfiguration = CreateMockInternalConfiguration();
manager.SetConfiguration(mockConfiguration.Object);
Assert.Same(mockLoadedConfig.Object, manager.GetConfiguration());
mockLoadedConfig.Verify(m => m.Lock());
mockConfiguration.Verify(m => m.Lock(), Times.Never());
}
[Fact]
public void SetConfiguration_throws_if_an_attempt_is_made_to_set_a_different_configuration_type()
{
var manager = CreateManager();
var configuration1 = new FakeConfiguration();
var mockInternalConfiguration1 = CreateMockInternalConfiguration(configuration1);
var configuration2 = new Mock<DbConfiguration>().Object;
var mockInternalConfiguration2 = CreateMockInternalConfiguration(configuration2);
manager.SetConfiguration(mockInternalConfiguration1.Object);
Assert.Equal(
Strings.ConfigurationSetTwice(configuration2.GetType().Name, configuration1.GetType().Name),
Assert.Throws<InvalidOperationException>(() => manager.SetConfiguration(mockInternalConfiguration2.Object)).Message);
}
[Fact]
public void SetConfiguration_throws_if_an_attempt_is_made_to_set_a_configuration_after_the_default_has_already_been_used()
{
var manager = CreateManager();
var dbConfiguration = new Mock<DbConfiguration>().Object;
var mockInternalConfiguration = CreateMockInternalConfiguration(dbConfiguration);
manager.GetConfiguration(); // Initialize default
Assert.Equal(
Strings.DefaultConfigurationUsedBeforeSet(dbConfiguration.GetType().Name),
Assert.Throws<InvalidOperationException>(() => manager.SetConfiguration(mockInternalConfiguration.Object)).Message);
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void SetConfiguration_can_be_called_from_multiple_threads_concurrently_and_only_one_will_win()
{
ConfigurationThreadTest(
m => { },
m => m.SetConfiguration(new FunctionalTestsConfiguration().InternalConfiguration));
}
}
public class EnsureLoadedForContext : TestBase
{
[Fact]
public void EnsureLoadedForContext_loads_configuration_from_context_assembly_if_none_was_previously_used()
{
var foundConfiguration = CreateMockInternalConfiguration().Object;
var mockFinder = new Mock<DbConfigurationFinder>();
mockFinder.Setup(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny<IEnumerable<Type>>())).Returns(
foundConfiguration);
var manager = CreateManager(null, mockFinder);
manager.EnsureLoadedForContext(typeof(FakeContext));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()));
Assert.Same(foundConfiguration, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_given_context_is_exactly_DbContext()
{
var mockFinder = new Mock<DbConfigurationFinder>();
CreateManager(null, mockFinder).EnsureLoadedForContext(typeof(DbContext));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>()), Times.Never());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_assembly_has_already_been_checked()
{
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(null, mockFinder);
manager.EnsureLoadedForContext(typeof(FakeContext));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()), Times.Once());
manager.EnsureLoadedForContext(typeof(FakeContext));
// Finder has not been used again
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()), Times.Once());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_an_override_configuration_has_been_pushed()
{
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(null, mockFinder);
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>()), Times.Once());
manager.EnsureLoadedForContext(typeof(FakeContext));
// Finder has not been used again
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>()), Times.Once());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_none_was_previously_used_and_no_configuration_is_found_in_assembly()
{
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(null, mockFinder);
manager.EnsureLoadedForContext(typeof(FakeContext));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()));
var mockInternalConfiguration = CreateMockInternalConfiguration();
manager.SetConfiguration(mockInternalConfiguration.Object);
Assert.Same(mockInternalConfiguration.Object, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_one_was_previously_used_but_no_configuration_is_found_in_assembly()
{
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(null, mockFinder);
var configuration = manager.GetConfiguration();
manager.EnsureLoadedForContext(typeof(FakeContext));
mockFinder.Verify(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()));
Assert.Same(configuration, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_one_was_previously()
{
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(null, mockFinder);
var configuration = manager.GetConfiguration();
manager.EnsureLoadedForContext(typeof(FakeContext));
mockFinder.Verify(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()));
Assert.Same(configuration, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_configuration_in_assembly_is_the_same_as_was_previously_used()
{
var mockInternalConfiguration = CreateMockInternalConfiguration();
var configuration = mockInternalConfiguration.Object;
var mockFinder = new Mock<DbConfigurationFinder>();
mockFinder.Setup(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()))
.Returns(configuration.Owner.GetType());
var manager = CreateManager(null, mockFinder);
manager.SetConfiguration(configuration);
manager.EnsureLoadedForContext(typeof(FakeContext));
mockFinder.Verify(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()));
Assert.Same(configuration, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_throws_if_found_configuration_does_not_match_previously_used_configuration()
{
var mockInternalConfiguration = CreateMockInternalConfiguration();
var mockFinder = new Mock<DbConfigurationFinder>();
mockFinder.Setup(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()))
.Returns(typeof(FakeConfiguration));
var manager = CreateManager(null, mockFinder);
manager.SetConfiguration(mockInternalConfiguration.Object);
Assert.Equal(
Strings.SetConfigurationNotDiscovered(mockInternalConfiguration.Object.Owner.GetType().Name, typeof(FakeContext).Name),
Assert.Throws<InvalidOperationException>(
() => manager.EnsureLoadedForContext(typeof(FakeContext))).Message);
}
[Fact]
public void EnsureLoadedForContext_throws_if_configuration_is_found_but_default_was_previously_used()
{
var configuration = new Mock<DbConfiguration>().Object;
var mockFinder = new Mock<DbConfigurationFinder>();
mockFinder.Setup(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny<IEnumerable<Type>>()))
.Returns(configuration.GetType());
var manager = CreateManager(null, mockFinder);
manager.GetConfiguration();
Assert.Equal(
Strings.ConfigurationNotDiscovered(configuration.GetType().Name),
Assert.Throws<InvalidOperationException>(
() => manager.EnsureLoadedForContext(typeof(FakeContext))).Message);
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_configuration_was_set_but_is_not_found_in_context_assembly()
{
var configuration = CreateMockInternalConfiguration().Object;
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(null, mockFinder);
manager.SetConfiguration(configuration);
manager.EnsureLoadedForContext(typeof(FakeContext));
Assert.Same(configuration, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_if_configuration_is_specified_in_config_file()
{
var mockLoadedConfig = CreateMockInternalConfiguration();
var mockLoader = new Mock<DbConfigurationLoader>();
mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny<AppConfig>())).Returns(true);
mockLoader.Setup(m => m.TryLoadFromConfig(It.IsAny<AppConfig>())).Returns(mockLoadedConfig.Object);
var mockInternalConfiguration = CreateMockInternalConfiguration();
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(mockLoader, mockFinder);
manager.SetConfiguration(mockInternalConfiguration.Object);
manager.EnsureLoadedForContext(typeof(FakeContext));
Assert.Same(mockLoadedConfig.Object, manager.GetConfiguration());
}
[Fact]
public void EnsureLoadedForContext_does_not_throw_even_if_finder_would_throw_if_configuration_is_specified_in_config_file()
{
var mockLoadedConfig = CreateMockInternalConfiguration();
var mockLoader = new Mock<DbConfigurationLoader>();
mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny<AppConfig>())).Returns(true);
mockLoader.Setup(m => m.TryLoadFromConfig(It.IsAny<AppConfig>())).Returns(mockLoadedConfig.Object);
var mockInternalConfiguration = CreateMockInternalConfiguration();
var mockFinder = new Mock<DbConfigurationFinder>();
mockFinder
.Setup(m => m.TryCreateConfiguration(It.IsAny<Type>(), It.IsAny<IEnumerable<Type>>()))
.Throws<InvalidOperationException>();
mockFinder
.Setup(m => m.TryFindConfigurationType(It.IsAny<Type>(), It.IsAny<IEnumerable<Type>>()))
.Throws<InvalidOperationException>();
var manager = CreateManager(mockLoader, mockFinder);
manager.SetConfiguration(mockInternalConfiguration.Object);
manager.EnsureLoadedForContext(typeof(FakeContext));
Assert.Same(mockLoadedConfig.Object, manager.GetConfiguration());
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void EnsureLoadedForContext_can_be_called_from_multiple_threads_concurrently_before_configuration_has_been_used()
{
ConfigurationThreadTest(
m => { },
m => m.EnsureLoadedForContext(typeof(SimpleModelContext)));
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void EnsureLoadedForContext_can_be_called_from_multiple_threads_concurrently_after_push_and_pop()
{
ConfigurationThreadTest(
m =>
{
m.PushConfiguration(AppConfig.DefaultInstance, typeof(SimpleModelContext));
m.PopConfiguration(AppConfig.DefaultInstance);
},
m => m.EnsureLoadedForContext(typeof(SimpleModelContext)));
}
}
public class PushConfiguration : TestBase
{
[Fact]
public void PushConfugiration_pushes_and_locks_configuration_from_config_if_found()
{
var mockConfiguration = new Mock<InternalConfiguration>();
var mockLoader = new Mock<DbConfigurationLoader>();
mockLoader.Setup(m => m.TryLoadFromConfig(AppConfig.DefaultInstance)).Returns(mockConfiguration.Object);
mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny<AppConfig>())).Returns(true);
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(mockLoader, mockFinder);
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
mockConfiguration.Verify(m => m.Lock());
Assert.Same(mockConfiguration.Object, manager.GetConfiguration());
mockLoader.Verify(m => m.TryLoadFromConfig(AppConfig.DefaultInstance));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>()), Times.Never());
}
[Fact]
public void PushConfugiration_pushes_and_locks_configuration_discovered_in_context_assembly_if_found()
{
var mockConfiguration = new Mock<InternalConfiguration>();
var mockLoader = new Mock<DbConfigurationLoader>();
var mockFinder = new Mock<DbConfigurationFinder>();
mockFinder.Setup(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>())).Returns(
mockConfiguration.Object);
var manager = CreateManager(mockLoader, mockFinder);
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
mockConfiguration.Verify(m => m.Lock());
Assert.Same(mockConfiguration.Object, manager.GetConfiguration());
mockLoader.Verify(m => m.TryLoadFromConfig(AppConfig.DefaultInstance));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>()));
}
[Fact]
public void PushConfugiration_pushes_default_configuration_if_no_other_found()
{
var mockLoader = new Mock<DbConfigurationLoader>();
var mockFinder = new Mock<DbConfigurationFinder>();
var manager = CreateManager(mockLoader, mockFinder);
var defaultConfiguration = manager.GetConfiguration();
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
Assert.NotSame(defaultConfiguration, manager.GetConfiguration());
mockLoader.Verify(m => m.TryLoadFromConfig(AppConfig.DefaultInstance));
mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny<IEnumerable<Type>>()));
}
[Fact]
public void AppConfigResolver_is_added_to_pushed_configuration()
{
var mockConfiguration = new Mock<InternalConfiguration>();
var mockLoader = new Mock<DbConfigurationLoader>();
mockLoader.Setup(m => m.TryLoadFromConfig(AppConfig.DefaultInstance)).Returns(mockConfiguration.Object);
mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny<AppConfig>())).Returns(true);
CreateManager(mockLoader).PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
mockConfiguration.Verify(m => m.AddAppConfigResolver(It.IsAny<AppConfigDependencyResolver>()));
}
[Fact]
public void PushConfugiration_switches_in_original_root_resolver()
{
var mockConfiguration = new Mock<InternalConfiguration>();
var mockLoader = new Mock<DbConfigurationLoader>();
mockLoader.Setup(m => m.TryLoadFromConfig(AppConfig.DefaultInstance)).Returns(mockConfiguration.Object);
mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny<AppConfig>())).Returns(true);
var manager = CreateManager(mockLoader);
var defaultConfiguration = manager.GetConfiguration();
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
mockConfiguration.Verify(m => m.SwitchInRootResolver(defaultConfiguration.RootResolver));
}
/// <summary>
/// This test makes calls from multiple threads such that we have at least some chance of finding threading
/// issues. As with any test of this type just because the test passes does not mean that the code is
/// correct. On the other hand if this test ever fails (EVEN ONCE) then we know there is a problem to
/// be investigated. DON'T just re-run and think things are okay if the test then passes.
/// </summary>
[Fact]
public void Configurations_can_be_pushed_and_popped_from_multiple_threads_concurrently()
{
for (var i = 0; i < 30; i++)
{
var manager = new DbConfigurationManager(new DbConfigurationLoader(), new DbConfigurationFinder());
var config = manager.GetConfiguration();
ExecuteInParallel(
() =>
{
var appConfig = new AppConfig(new ConnectionStringSettingsCollection());
manager.PushConfiguration(appConfig, typeof(SimpleModelContext));
manager.PopConfiguration(appConfig);
});
Assert.Same(config, manager.GetConfiguration());
}
}
}
public class PopConfiguration : TestBase
{
[Fact]
public void PopConfiguration_removes_the_first_configuration_associated_with_the_given_AppConfig()
{
var manager = CreateManager();
var mockInternalConfiguration = new Mock<InternalConfiguration>
{
CallBase = true
};
var mockDbConfiguration = new Mock<DbConfiguration>();
mockDbConfiguration.Setup(m => m.InternalConfiguration).Returns(mockInternalConfiguration.Object);
mockInternalConfiguration.Setup(m => m.Owner).Returns(mockDbConfiguration.Object);
var appConfig1 = AppConfig.DefaultInstance;
var appConfig2 = new AppConfig(ConfigurationManager.ConnectionStrings);
manager.SetConfiguration(mockInternalConfiguration.Object);
manager.PushConfiguration(appConfig1, typeof(DbContext));
var pushed1 = manager.GetConfiguration();
manager.PushConfiguration(appConfig2, typeof(DbContext));
manager.PopConfiguration(appConfig2);
Assert.Same(pushed1, manager.GetConfiguration());
manager.PopConfiguration(appConfig1);
Assert.Same(mockInternalConfiguration.Object, manager.GetConfiguration());
}
[Fact]
public void PopConfiguration_does_nothing_if_no_configuration_is_associated_with_the_given_AppConfig()
{
var manager = CreateManager();
manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext));
var pushed1 = manager.GetConfiguration();
manager.PopConfiguration(new AppConfig(ConfigurationManager.ConnectionStrings));
Assert.Same(pushed1, manager.GetConfiguration());
}
}
public class AddOnLockingHandler
{
[Fact]
public void Adding_handler_after_configuration_is_in_use_throws()
{
var manager = CreateManager();
manager.GetConfiguration();
Assert.Equal(
Strings.AddHandlerToInUseConfiguration,
Assert.Throws<InvalidOperationException>(() => manager.AddOnLockingHandler((_, __) => { })).Message);
}
}
public class OnLocking
{
private readonly IDbDependencyResolver _snapshot;
private readonly Mock<InternalConfiguration> _configuration;
public OnLocking()
{
_snapshot = new Mock<IDbDependencyResolver>().Object;
_configuration = CreateMockInternalConfiguration(null, _snapshot);
}
[Fact]
public void OnLocking_calls_all_added_handlers_and_passes_in_correct_configuration()
{
var manager = CreateManager();
manager.OnLocking(_configuration.Object); // No throw when no handlers registered
manager.AddOnLockingHandler(Handler1);
manager.AddOnLockingHandler(Handler2);
manager.AddOnLockingHandler(Handler3);
manager.OnLocking(_configuration.Object);
Assert.Equal(1, Handler1Called);
Assert.Equal(1, Handler2Called);
Assert.Equal(1, Handler3Called);
manager.RemoveOnLockingHandler(Handler2);
manager.OnLocking(_configuration.Object);
Assert.Equal(2, Handler1Called);
Assert.Equal(1, Handler2Called);
Assert.Equal(2, Handler3Called);
}
private int Handler1Called { get; set; }
private void Handler1(object sender, DbConfigurationEventArgs args)
{
Assert.Same(_configuration.Object.Owner, sender);
Assert.Same(_snapshot, args.ResolverSnapshot);
Handler1Called++;
}
private int Handler2Called { get; set; }
private void Handler2(object sender, DbConfigurationEventArgs args)
{
Assert.Same(_configuration.Object.Owner, sender);
Assert.Same(_snapshot, args.ResolverSnapshot);
Handler2Called++;
}
private int Handler3Called { get; set; }
private void Handler3(object sender, DbConfigurationEventArgs args)
{
Assert.Same(_configuration.Object.Owner, sender);
Assert.Same(_snapshot, args.ResolverSnapshot);
Handler3Called++;
}
}
private static DbConfigurationManager CreateManager(
Mock<DbConfigurationLoader> mockLoader = null,
Mock<DbConfigurationFinder> mockFinder = null)
{
return new DbConfigurationManager(
(mockLoader ?? new Mock<DbConfigurationLoader>()).Object,
(mockFinder ?? new Mock<DbConfigurationFinder>()).Object);
}
public class FakeConfiguration : DbConfiguration
{
}
public class FakeContext : DbContext
{
}
private static Mock<InternalConfiguration> CreateMockInternalConfiguration(
DbConfiguration dbConfiguration = null, IDbDependencyResolver snapshot = null)
{
var mockInternalConfiguration = new Mock<InternalConfiguration>();
if (dbConfiguration == null)
{
var mockDbConfiguration = new Mock<DbConfiguration>();
mockDbConfiguration.Setup(m => m.InternalConfiguration).Returns(mockInternalConfiguration.Object);
dbConfiguration = mockDbConfiguration.Object;
}
mockInternalConfiguration.Setup(m => m.Owner).Returns(dbConfiguration);
mockInternalConfiguration.Setup(m => m.ResolverSnapshot).Returns(snapshot);
return mockInternalConfiguration;
}
private static void ConfigurationThreadTest(Action<DbConfigurationManager> beforeThreads, Action<DbConfigurationManager> inThreads)
{
for (var i = 0; i < 30; i++)
{
var configurationBag = new ConcurrentBag<InternalConfiguration>();
var manager = new DbConfigurationManager(new DbConfigurationLoader(), new DbConfigurationFinder());
manager.SetConfiguration(new FunctionalTestsConfiguration().InternalConfiguration);
beforeThreads(manager);
ExecuteInParallel(
() =>
{
inThreads(manager);
configurationBag.Add(manager.GetConfiguration());
});
Assert.Equal(20, configurationBag.Count);
Assert.True(configurationBag.All(c => manager.GetConfiguration() == c));
}
}
}
}