// 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 { CallBase = true }; var mockDbConfiguration = new Mock(); 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()); } /// /// 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. /// [Fact] public void GetConfiguration_for_default_value_can_be_called_from_multiple_threads_concurrently() { ConfigurationThreadTest(m => { }, m => { }); } /// /// 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. /// [Fact] public void GetConfiguration_for_pushed_config_can_be_called_from_multiple_threads_concurrently() { ConfigurationThreadTest(m => m.PushConfiguration(AppConfig.DefaultInstance, typeof(SimpleModelContext)), m => { }); } /// /// 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. /// [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(); mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny())).Returns(true); mockLoader.Setup(m => m.TryLoadFromConfig(It.IsAny())).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().Object; var mockInternalConfiguration2 = CreateMockInternalConfiguration(configuration2); manager.SetConfiguration(mockInternalConfiguration1.Object); Assert.Equal( Strings.ConfigurationSetTwice(configuration2.GetType().Name, configuration1.GetType().Name), Assert.Throws(() => 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().Object; var mockInternalConfiguration = CreateMockInternalConfiguration(dbConfiguration); manager.GetConfiguration(); // Initialize default Assert.Equal( Strings.DefaultConfigurationUsedBeforeSet(dbConfiguration.GetType().Name), Assert.Throws(() => manager.SetConfiguration(mockInternalConfiguration.Object)).Message); } /// /// 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. /// [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(); mockFinder.Setup(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny>())).Returns( foundConfiguration); var manager = CreateManager(null, mockFinder); manager.EnsureLoadedForContext(typeof(FakeContext)); mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny>())); Assert.Same(foundConfiguration, manager.GetConfiguration()); } [Fact] public void EnsureLoadedForContext_does_not_throw_if_given_context_is_exactly_DbContext() { var mockFinder = new Mock(); CreateManager(null, mockFinder).EnsureLoadedForContext(typeof(DbContext)); mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny>()), Times.Never()); } [Fact] public void EnsureLoadedForContext_does_not_throw_if_assembly_has_already_been_checked() { var mockFinder = new Mock(); var manager = CreateManager(null, mockFinder); manager.EnsureLoadedForContext(typeof(FakeContext)); mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny>()), Times.Once()); manager.EnsureLoadedForContext(typeof(FakeContext)); // Finder has not been used again mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny>()), Times.Once()); } [Fact] public void EnsureLoadedForContext_does_not_throw_if_an_override_configuration_has_been_pushed() { var mockFinder = new Mock(); var manager = CreateManager(null, mockFinder); manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext)); mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny>()), Times.Once()); manager.EnsureLoadedForContext(typeof(FakeContext)); // Finder has not been used again mockFinder.Verify(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny>()), 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(); var manager = CreateManager(null, mockFinder); manager.EnsureLoadedForContext(typeof(FakeContext)); mockFinder.Verify(m => m.TryCreateConfiguration(typeof(FakeContext), It.IsAny>())); 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(); var manager = CreateManager(null, mockFinder); var configuration = manager.GetConfiguration(); manager.EnsureLoadedForContext(typeof(FakeContext)); mockFinder.Verify(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny>())); Assert.Same(configuration, manager.GetConfiguration()); } [Fact] public void EnsureLoadedForContext_does_not_throw_if_one_was_previously() { var mockFinder = new Mock(); var manager = CreateManager(null, mockFinder); var configuration = manager.GetConfiguration(); manager.EnsureLoadedForContext(typeof(FakeContext)); mockFinder.Verify(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny>())); 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(); mockFinder.Setup(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny>())) .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>())); 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(); mockFinder.Setup(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny>())) .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( () => manager.EnsureLoadedForContext(typeof(FakeContext))).Message); } [Fact] public void EnsureLoadedForContext_throws_if_configuration_is_found_but_default_was_previously_used() { var configuration = new Mock().Object; var mockFinder = new Mock(); mockFinder.Setup(m => m.TryFindConfigurationType(typeof(FakeContext), It.IsAny>())) .Returns(configuration.GetType()); var manager = CreateManager(null, mockFinder); manager.GetConfiguration(); Assert.Equal( Strings.ConfigurationNotDiscovered(configuration.GetType().Name), Assert.Throws( () => 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(); 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(); mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny())).Returns(true); mockLoader.Setup(m => m.TryLoadFromConfig(It.IsAny())).Returns(mockLoadedConfig.Object); var mockInternalConfiguration = CreateMockInternalConfiguration(); var mockFinder = new Mock(); 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(); mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny())).Returns(true); mockLoader.Setup(m => m.TryLoadFromConfig(It.IsAny())).Returns(mockLoadedConfig.Object); var mockInternalConfiguration = CreateMockInternalConfiguration(); var mockFinder = new Mock(); mockFinder .Setup(m => m.TryCreateConfiguration(It.IsAny(), It.IsAny>())) .Throws(); mockFinder .Setup(m => m.TryFindConfigurationType(It.IsAny(), It.IsAny>())) .Throws(); var manager = CreateManager(mockLoader, mockFinder); manager.SetConfiguration(mockInternalConfiguration.Object); manager.EnsureLoadedForContext(typeof(FakeContext)); Assert.Same(mockLoadedConfig.Object, manager.GetConfiguration()); } /// /// 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. /// [Fact] public void EnsureLoadedForContext_can_be_called_from_multiple_threads_concurrently_before_configuration_has_been_used() { ConfigurationThreadTest( m => { }, m => m.EnsureLoadedForContext(typeof(SimpleModelContext))); } /// /// 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. /// [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(); var mockLoader = new Mock(); mockLoader.Setup(m => m.TryLoadFromConfig(AppConfig.DefaultInstance)).Returns(mockConfiguration.Object); mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny())).Returns(true); var mockFinder = new Mock(); 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>()), Times.Never()); } [Fact] public void PushConfugiration_pushes_and_locks_configuration_discovered_in_context_assembly_if_found() { var mockConfiguration = new Mock(); var mockLoader = new Mock(); var mockFinder = new Mock(); mockFinder.Setup(m => m.TryCreateConfiguration(typeof(DbContext), It.IsAny>())).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>())); } [Fact] public void PushConfugiration_pushes_default_configuration_if_no_other_found() { var mockLoader = new Mock(); var mockFinder = new Mock(); 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>())); } [Fact] public void AppConfigResolver_is_added_to_pushed_configuration() { var mockConfiguration = new Mock(); var mockLoader = new Mock(); mockLoader.Setup(m => m.TryLoadFromConfig(AppConfig.DefaultInstance)).Returns(mockConfiguration.Object); mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny())).Returns(true); CreateManager(mockLoader).PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext)); mockConfiguration.Verify(m => m.AddAppConfigResolver(It.IsAny())); } [Fact] public void PushConfugiration_switches_in_original_root_resolver() { var mockConfiguration = new Mock(); var mockLoader = new Mock(); mockLoader.Setup(m => m.TryLoadFromConfig(AppConfig.DefaultInstance)).Returns(mockConfiguration.Object); mockLoader.Setup(m => m.AppConfigContainsDbConfigurationType(It.IsAny())).Returns(true); var manager = CreateManager(mockLoader); var defaultConfiguration = manager.GetConfiguration(); manager.PushConfiguration(AppConfig.DefaultInstance, typeof(DbContext)); mockConfiguration.Verify(m => m.SwitchInRootResolver(defaultConfiguration.RootResolver)); } /// /// 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. /// [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 { CallBase = true }; var mockDbConfiguration = new Mock(); 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(() => manager.AddOnLockingHandler((_, __) => { })).Message); } } public class OnLocking { private readonly IDbDependencyResolver _snapshot; private readonly Mock _configuration; public OnLocking() { _snapshot = new Mock().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 mockLoader = null, Mock mockFinder = null) { return new DbConfigurationManager( (mockLoader ?? new Mock()).Object, (mockFinder ?? new Mock()).Object); } public class FakeConfiguration : DbConfiguration { } public class FakeContext : DbContext { } private static Mock CreateMockInternalConfiguration( DbConfiguration dbConfiguration = null, IDbDependencyResolver snapshot = null) { var mockInternalConfiguration = new Mock(); if (dbConfiguration == null) { var mockDbConfiguration = new Mock(); 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 beforeThreads, Action inThreads) { for (var i = 0; i < 30; i++) { var configurationBag = new ConcurrentBag(); 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)); } } } }