848 lines
35 KiB
C#
848 lines
35 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
namespace ProductivityApiUnitTests
|
|
{
|
|
using System;
|
|
using System.Data.Entity;
|
|
using System.Data.Entity.Infrastructure;
|
|
using System.Data.Entity.Internal;
|
|
using System.Data.Entity.Migrations;
|
|
using System.Data.Entity.Migrations.History;
|
|
using System.Data.Entity.Resources;
|
|
using System.Data.SqlClient;
|
|
using System.Xml.Linq;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
/// <summary>
|
|
/// Unit tests for database initialization.
|
|
/// </summary>
|
|
public class DatabaseInitializationTests : TestBase
|
|
{
|
|
#region Helpers
|
|
|
|
/// <summary>
|
|
/// Used as a fake context type for tests that don't actually register a strategy.
|
|
/// </summary>
|
|
public class FakeNoRegContext : DbContext
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Negative initialization strategy tests
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseAlways_throws_when_given_a_null_context()
|
|
{
|
|
Assert.Equal(
|
|
"context",
|
|
Assert.Throws<ArgumentNullException>(() => new DropCreateDatabaseAlways<DbContext>().InitializeDatabase(null)).ParamName);
|
|
}
|
|
|
|
[Fact]
|
|
public void CreateDatabaseIfNotExists_throws_when_given_a_null_context()
|
|
{
|
|
Assert.Equal(
|
|
"context",
|
|
Assert.Throws<ArgumentNullException>(() => new CreateDatabaseIfNotExists<DbContext>().InitializeDatabase(null)).ParamName);
|
|
}
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseIfModelChanges_throws_when_given_a_null_context()
|
|
{
|
|
Assert.Equal(
|
|
"context",
|
|
Assert.Throws<ArgumentNullException>(() => new DropCreateDatabaseIfModelChanges<DbContext>().InitializeDatabase(null)).
|
|
ParamName);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateDatabaseToLatestVersion_ctor_throws_when_given_null_connection_name()
|
|
{
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("connectionStringName"),
|
|
Assert.Throws<ArgumentException>(() => new MigrateDatabaseToLatestVersion<EmptyContext, TestMigrationsConfiguration>(null)).
|
|
Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateDatabaseToLatestVersion_ctor_throws_when_given_empty_connection_name()
|
|
{
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("connectionStringName"),
|
|
Assert.Throws<ArgumentException>(() => new MigrateDatabaseToLatestVersion<EmptyContext, TestMigrationsConfiguration>(" ")).
|
|
Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateDatabaseToLatestVersion_throws_when_given_invalid_connection_name()
|
|
{
|
|
var init = new MigrateDatabaseToLatestVersion<EmptyContext, TestMigrationsConfiguration>("YouWontFindMe");
|
|
|
|
Assert.Equal(
|
|
Strings.DbContext_ConnectionStringNotFound("YouWontFindMe"),
|
|
Assert.Throws<InvalidOperationException>(() => init.InitializeDatabase(new EmptyContext())).Message);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Positive DropCreateDatabaseAlways strategy tests
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseAlways_performs_delete_create_and_seeding()
|
|
{
|
|
var tracker = new DatabaseInitializerTracker<FakeNoRegContext, DropCreateDatabaseAlways<FakeNoRegContext>>(
|
|
databaseExists: false);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("DeleteIfExists Exists CreateDatabase Seed", tracker.Result);
|
|
}
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseAlways_performs_delete_create_and_seeding_even_if_database_exists_and_model_matches()
|
|
{
|
|
var tracker = new DatabaseInitializerTracker<FakeNoRegContext, DropCreateDatabaseAlways<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: true);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("DeleteIfExists Exists CreateDatabase Seed", tracker.Result);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Positive CreateDatabaseIfNotExists strategy tests
|
|
|
|
[Fact]
|
|
public void CreateDatabaseIfNotExists_creates_and_seeds_database_if_not_exists()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeNoRegContext, CreateDatabaseIfNotExists<FakeNoRegContext>>(databaseExists: false);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("Exists CreateDatabase Seed", tracker.Result);
|
|
}
|
|
|
|
[Fact]
|
|
public void CreateDatabaseIfNotExists_does_nothing_if_database_exists_and_model_matches()
|
|
{
|
|
var tracker = new DatabaseInitializerTracker<FakeNoRegContext, CreateDatabaseIfNotExists<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: true);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("Exists", tracker.Result);
|
|
}
|
|
|
|
[Fact]
|
|
public void CreateDatabaseIfNotExists_throws_if_database_exists_and_model_does_not_match()
|
|
{
|
|
var tracker = new DatabaseInitializerTracker<FakeNoRegContext, CreateDatabaseIfNotExists<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: false);
|
|
|
|
Assert.Equal(
|
|
Strings.DatabaseInitializationStrategy_ModelMismatch(tracker.Context.GetType().Name),
|
|
Assert.Throws<InvalidOperationException>(() => tracker.ExecuteStrategy()).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void CreateDatabaseIfNotExists_does_nothing_if_database_exists_but_has_no_metadata()
|
|
{
|
|
var tracker = new DatabaseInitializerTracker<FakeNoRegContext, CreateDatabaseIfNotExists<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: true, hasMetadata: false);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("Exists", tracker.Result);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Positive DropCreateDatabaseIfModelChanges strategy tests
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseIfModelChanges_creates_and_seeds_database_if_not_exists()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeNoRegContext, DropCreateDatabaseIfModelChanges<FakeNoRegContext>>(databaseExists: false);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("Exists Exists CreateDatabase Seed", tracker.Result);
|
|
}
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseIfModelChanges_does_nothing_if_database_exists_and_model_matches()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeNoRegContext, DropCreateDatabaseIfModelChanges<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: true);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("Exists", tracker.Result);
|
|
}
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseIfModelChanges_recreates_database_if_database_exists_and_model_does_not_match()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeNoRegContext, DropCreateDatabaseIfModelChanges<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: false);
|
|
|
|
tracker.ExecuteStrategy();
|
|
|
|
Assert.Equal("Exists DeleteIfExists Exists CreateDatabase Seed", tracker.Result);
|
|
}
|
|
|
|
[Fact]
|
|
public void DropCreateDatabaseIfModelChanges_throws_if_database_exists_but_has_no_metadata()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeNoRegContext, DropCreateDatabaseIfModelChanges<FakeNoRegContext>>(
|
|
databaseExists: true, modelCompatible: true, hasMetadata: false);
|
|
|
|
Assert.Equal(Strings.Database_NoDatabaseMetadata, Assert.Throws<NotSupportedException>(() => tracker.ExecuteStrategy()).Message);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Positive MigrateDatabaseToLatestVersion strategy tests
|
|
|
|
public class EmptyContext : DbContext
|
|
{
|
|
}
|
|
|
|
private class TestMigrationsConfiguration : DbMigrationsConfiguration<EmptyContext>
|
|
{
|
|
public TestMigrationsConfiguration()
|
|
{
|
|
MigrationsNamespace = "You.Wont.Find.Any.Migrations.Here";
|
|
AutomaticMigrationsEnabled = true;
|
|
}
|
|
|
|
protected override void Seed(EmptyContext context)
|
|
{
|
|
SeedCalled = true;
|
|
SeedDatabase = context.Database.Connection.Database;
|
|
}
|
|
|
|
public static bool SeedCalled { get; set; }
|
|
public static string SeedDatabase { get; set; }
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateDatabaseToLatestVersion_invokes_migrations_pipeline_to_latest_version()
|
|
{
|
|
var init = new MigrateDatabaseToLatestVersion<EmptyContext, TestMigrationsConfiguration>();
|
|
|
|
TestMigrationsConfiguration.SeedCalled = false;
|
|
|
|
init.InitializeDatabase(new EmptyContext());
|
|
|
|
// If seed gets called we know the migrations pipeline was invoked to update to the latest version
|
|
Assert.True(TestMigrationsConfiguration.SeedCalled);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateDatabaseToLatestVersion_use_connection_name_from_config_file()
|
|
{
|
|
var init =
|
|
new MigrateDatabaseToLatestVersion<EmptyContext, TestMigrationsConfiguration>(
|
|
"MigrateDatabaseToLatestVersionNamedConnectionTest");
|
|
|
|
TestMigrationsConfiguration.SeedDatabase = null;
|
|
|
|
init.InitializeDatabase(new EmptyContext());
|
|
|
|
Assert.Equal("MigrationInitFromConfig", TestMigrationsConfiguration.SeedDatabase);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Positive Database.SetInitializer tests
|
|
|
|
public class FakeForSirdi : DbContextUsingMockInternalContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void SetInitializer_registers_different_initializer()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForSirdi>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
var mock = new Mock<InternalContextForMockWithRealContext<FakeForSirdi>>();
|
|
mock.Setup(m => m.AppConfig).Returns(new AppConfig(CreateEmptyConfig()));
|
|
new Database(mock.Object).Initialize(force: true);
|
|
}
|
|
|
|
public class FakeForSirdifdct1 : DbContextUsingMockInternalContext
|
|
{
|
|
}
|
|
|
|
public class FakeForSirdifdct2 : DbContextUsingMockInternalContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void SetInitializer_registers_different_initializers_for_different_context_types()
|
|
{
|
|
var mockInitializer1 = new Mock<IDatabaseInitializer<FakeForSirdifdct1>>();
|
|
Database.SetInitializer(mockInitializer1.Object);
|
|
|
|
var mockInitializer2 = new Mock<IDatabaseInitializer<FakeForSirdifdct2>>();
|
|
Database.SetInitializer(mockInitializer2.Object);
|
|
|
|
// Initialize for first type and verify correct initializer called
|
|
var mock = new Mock<InternalContextForMockWithRealContext<FakeForSirdifdct1>>();
|
|
mock.Setup(m => m.AppConfig).Returns(new AppConfig(CreateEmptyConfig()));
|
|
new Database(mock.Object).Initialize(force: true);
|
|
|
|
mockInitializer1.Verify(i => i.InitializeDatabase(It.IsAny<FakeForSirdifdct1>()), Times.Once());
|
|
mockInitializer2.Verify(i => i.InitializeDatabase(It.IsAny<FakeForSirdifdct2>()), Times.Never());
|
|
|
|
// Initialize for second type and verify correct initializer called
|
|
var mock2 = new Mock<InternalContextForMockWithRealContext<FakeForSirdifdct2>>();
|
|
mock2.Setup(m => m.AppConfig).Returns(new AppConfig(CreateEmptyConfig()));
|
|
new Database(mock2.Object).Initialize(force: true);
|
|
|
|
mockInitializer1.Verify(i => i.InitializeDatabase(It.IsAny<FakeForSirdifdct1>()), Times.Once());
|
|
mockInitializer2.Verify(i => i.InitializeDatabase(It.IsAny<FakeForSirdifdct2>()), Times.Once());
|
|
}
|
|
|
|
public class FakeForCsiaftsctrfi : DbContextUsingMockInternalContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Calling_SetInitializer_again_for_the_same_context_type_replaces_first_initializer()
|
|
{
|
|
var mockInitializer1 = new Mock<IDatabaseInitializer<FakeForCsiaftsctrfi>>();
|
|
Database.SetInitializer(mockInitializer1.Object);
|
|
|
|
var mockInitializer2 = new Mock<IDatabaseInitializer<FakeForCsiaftsctrfi>>();
|
|
Database.SetInitializer(mockInitializer2.Object);
|
|
|
|
var mock = new Mock<InternalContextForMockWithRealContext<FakeForCsiaftsctrfi>>();
|
|
mock.Setup(m => m.AppConfig).Returns(new AppConfig(CreateEmptyConfig()));
|
|
new Database(mock.Object).Initialize(force: true);
|
|
|
|
mockInitializer1.Verify(i => i.InitializeDatabase(It.IsAny<FakeForCsiaftsctrfi>()), Times.Never());
|
|
mockInitializer2.Verify(i => i.InitializeDatabase(It.IsAny<FakeForCsiaftsctrfi>()), Times.Once());
|
|
}
|
|
|
|
public class FakeForDisicdoine : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Default_initialization_strategy_is_CreateDatabaseIfNotExists()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeForDisicdoine, DropCreateDatabaseAlways<FakeForDisicdoine>>(databaseExists: false);
|
|
|
|
tracker.Context.Database.Initialize(force: true);
|
|
|
|
Assert.Equal("UseTempObjectContext Exists CreateDatabase DisposeTempObjectContext", tracker.Result);
|
|
}
|
|
|
|
public class FakeForDisirbcsiwn : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Default_initialization_strategy_is_removed_by_calling_SetInitializer_with_null()
|
|
{
|
|
var tracker =
|
|
new DatabaseInitializerTracker<FakeForDisirbcsiwn, DropCreateDatabaseAlways<FakeForDisirbcsiwn>>(databaseExists: false);
|
|
|
|
var mockContextType = tracker.Context.GetType();
|
|
var initMethod = typeof(Database).GetMethod("SetInitializer").MakeGenericMethod(mockContextType);
|
|
initMethod.Invoke(null, new object[] { null });
|
|
|
|
tracker.Context.Database.Initialize(force: true);
|
|
|
|
Assert.Equal("UseTempObjectContext DisposeTempObjectContext", tracker.Result);
|
|
}
|
|
|
|
public class FakeForIscbrbcsin : DbContextUsingMockInternalContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Initialization_strategy_can_be_removed_by_calling_SetInitializer_null()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForIscbrbcsin>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
Database.SetInitializer<FakeForIscbrbcsin>(null);
|
|
|
|
var mock = new Mock<InternalContextForMockWithRealContext<FakeForIscbrbcsin>>();
|
|
mock.Setup(m => m.AppConfig).Returns(new AppConfig(CreateEmptyConfig()));
|
|
new Database(mock.Object).Initialize(force: true);
|
|
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForIscbrbcsin>()), Times.Never());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Database.Initialize (with force false) positive tests
|
|
|
|
public class FakeForEieiidhnabi : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Initialize_without_force_executes_initializer_if_database_has_not_already_been_initialized()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForEieiidhnabi>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
new FakeForEieiidhnabi().Database.Initialize(force: false);
|
|
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForEieiidhnabi>()), Times.Once());
|
|
}
|
|
|
|
public class FakeForEidneiidhabi : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Initialize_without_force_does_not_execute_initializer_if_database_has_already_been_initialized()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForEidneiidhabi>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
// This will call the initializer
|
|
new FakeForEidneiidhabi().Database.Initialize(force: true);
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForEidneiidhabi>()), Times.Once());
|
|
|
|
// This should not call it again
|
|
new FakeForEidneiidhabi().Database.Initialize(force: false);
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForEidneiidhabi>()), Times.Once());
|
|
}
|
|
|
|
public class FakeForIeiwdhnbi : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Initialize_executes_initializer_when_database_has_not_been_initialized()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForIeiwdhnbi>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
new FakeForIeiwdhnbi().Database.Initialize(force: true);
|
|
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForIeiwdhnbi>()), Times.Once());
|
|
}
|
|
|
|
public class FakeForIeiewdhabi : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Initialize_executes_initializer_even_when_database_has_already_been_initialized()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForIeiewdhabi>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
new FakeForIeiewdhabi().Database.Initialize(force: true);
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForIeiewdhabi>()), Times.Once());
|
|
|
|
new FakeForIeiewdhabi().Database.Initialize(force: true);
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForIeiewdhabi>()), Times.Exactly(2));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ModelMatches positive tests
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_model_was_not_created_with_Code_First_and_throwing_is_switched_off()
|
|
{
|
|
var mockInternalContext = new Mock<InternalContextForMock>
|
|
{
|
|
CallBase = true
|
|
};
|
|
mockInternalContext.Setup(c => c.CodeFirstModel).Returns((DbCompiledModel)null);
|
|
|
|
Assert.True(new Database(mockInternalContext.Object).CompatibleWithModel(throwIfNoMetadata: false));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Database initialization status positive tests
|
|
|
|
internal class NonInitializingLazyInternalContext : LazyInternalContext
|
|
{
|
|
public NonInitializingLazyInternalContext(IInternalConnection internalConnection, DbCompiledModel model)
|
|
: base(new Mock<DbContext>().Object, internalConnection, model)
|
|
{
|
|
}
|
|
|
|
protected override void InitializeContext()
|
|
{
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TempObjectContext and GetObjectContextWithoutDatabaseInitialization positive tests
|
|
|
|
public class FakeForGocwdidnid : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void GetObjectContextWithoutDatabaseInitialization_does_not_initialize_database()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<FakeForGocwdidnid>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
new FakeForGocwdidnid().InternalContext.GetObjectContextWithoutDatabaseInitialization();
|
|
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<FakeForGocwdidnid>()), Times.Never());
|
|
}
|
|
|
|
public class FakeForUtoccatoc : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void UseTempObjectContext_creates_a_temporary_object_context()
|
|
{
|
|
var internalContext = new FakeForUtoccatoc().InternalContext;
|
|
var realContext = internalContext.GetObjectContextWithoutDatabaseInitialization();
|
|
|
|
internalContext.UseTempObjectContext();
|
|
|
|
Assert.NotSame(realContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
|
|
internalContext.DisposeTempObjectContext();
|
|
|
|
Assert.Same(realContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
}
|
|
|
|
public class FakeForUtoccmtocotoc : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void UseTempObjectContext_called_multiple_times_only_creates_one_temporary_object_context()
|
|
{
|
|
var internalContext = new FakeForUtoccmtocotoc().InternalContext;
|
|
var realContext = internalContext.GetObjectContextWithoutDatabaseInitialization();
|
|
|
|
internalContext.UseTempObjectContext();
|
|
var fakeContext = internalContext.GetObjectContextWithoutDatabaseInitialization();
|
|
|
|
internalContext.UseTempObjectContext();
|
|
Assert.Same(fakeContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
|
|
internalContext.UseTempObjectContext();
|
|
Assert.Same(fakeContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
|
|
internalContext.DisposeTempObjectContext();
|
|
Assert.Same(fakeContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
|
|
internalContext.DisposeTempObjectContext();
|
|
Assert.Same(fakeContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
|
|
internalContext.DisposeTempObjectContext();
|
|
Assert.Same(realContext, internalContext.GetObjectContextWithoutDatabaseInitialization());
|
|
}
|
|
|
|
public class FakeForLctdtocdttc : DbContext
|
|
{
|
|
}
|
|
|
|
[Fact]
|
|
public void Last_call_to_DisposeTempObjectContext_disposes_the_temp_context()
|
|
{
|
|
var internalContext = new FakeForLctdtocdttc().InternalContext;
|
|
|
|
internalContext.UseTempObjectContext();
|
|
internalContext.UseTempObjectContext();
|
|
|
|
var fakeContext = internalContext.GetObjectContextWithoutDatabaseInitialization();
|
|
|
|
internalContext.DisposeTempObjectContext();
|
|
internalContext.DisposeTempObjectContext();
|
|
|
|
Assert.Throws<ObjectDisposedException>(() => fakeContext.SaveChanges()).ValidateMessage(
|
|
"ObjectContext_ObjectDisposed");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ModelMatches tests
|
|
|
|
private static Mock<InternalContextForMock<FakeNoRegContext>> CreateContextForCompatibleTest(
|
|
bool modelMatches, bool codeFirst = true)
|
|
{
|
|
var mockInternalContext = new Mock<InternalContextForMock<FakeNoRegContext>>();
|
|
mockInternalContext.Setup(c => c.CodeFirstModel).Returns(codeFirst ? new DbCompiledModel() : null);
|
|
mockInternalContext.Setup(c => c.QueryForModel()).Returns(new XDocument());
|
|
mockInternalContext.Setup(c => c.ModelMatches(It.IsAny<XDocument>())).Returns(modelMatches);
|
|
return mockInternalContext;
|
|
}
|
|
|
|
private static Mock<InternalContextForMock<FakeNoRegContext>> CreateContextForCompatibleTest(
|
|
string databaseHash, bool codeFirst = true)
|
|
{
|
|
var mockInternalContext = new Mock<InternalContextForMock<FakeNoRegContext>>();
|
|
mockInternalContext.Setup(c => c.CodeFirstModel).Returns(codeFirst ? new DbCompiledModel() : null);
|
|
mockInternalContext.Setup(c => c.QueryForModel()).Returns((XDocument)null);
|
|
mockInternalContext.Setup(c => c.QueryForModelHash()).Returns(databaseHash);
|
|
return mockInternalContext;
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_model_matches_database_and_method_is_asked_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest(modelMatches: true);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
|
|
Assert.True(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: true));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_model_matches_database_and_method_is_asked_not_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest(modelMatches: true);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
|
|
Assert.True(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: false));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_false_if_model_does_not_match_database_and_method_is_asked_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest(modelMatches: false);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
|
|
Assert.False(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: true));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_false_if_model_does_not_match_database_and_method_is_asked_not_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest(modelMatches: false);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
|
|
Assert.False(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: false));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_model_matches_database_using_model_hash_check_and_method_is_asked_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest("<Hash>");
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns("<Hash>");
|
|
|
|
Assert.True(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: true));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_model_matches_database_using_model_hash_check_and_method_is_asked_not_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest("<Hash>");
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns("<Hash>");
|
|
|
|
Assert.True(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: false));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_false_if_model_does_not_match_database_using_model_hash_check_and_method_is_asked_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest("<Hash1>");
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns("<Hash2>");
|
|
|
|
Assert.False(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: true));
|
|
}
|
|
|
|
[Fact]
|
|
public void
|
|
CompatibleWithModel_returns_false_if_model_does_not_match_database_using_model_hash_check_and_method_is_asked_not_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest("<Hash1>");
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns("<Hash2>");
|
|
|
|
Assert.False(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: false));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_model_is_not_from_code_first_and_method_is_asked_not_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest("<Hash>", codeFirst: false);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
|
|
Assert.True(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: false));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_returns_true_if_database_has_no_hash_and_method_is_asked_not_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest(null);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns("<Hash>");
|
|
|
|
Assert.True(
|
|
new ModelCompatibilityChecker()
|
|
.CompatibleWithModel(mockInternalContext.Object, mockHashFactory.Object, throwIfNoMetadata: false));
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_throws_if_model_is_not_from_code_first_and_method_is_asked_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest("<Hash>", codeFirst: false);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns((string)null);
|
|
|
|
Assert.Equal(
|
|
Strings.Database_NonCodeFirstCompatibilityCheck,
|
|
Assert.Throws<NotSupportedException>(
|
|
() => new ModelCompatibilityChecker().CompatibleWithModel(
|
|
mockInternalContext.Object,
|
|
mockHashFactory.Object,
|
|
throwIfNoMetadata: true)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void CompatibleWithModel_throws_if_database_has_no_hash_and_method_is_asked_to_throw()
|
|
{
|
|
var mockInternalContext = CreateContextForCompatibleTest(null);
|
|
var mockHashFactory = new Mock<ModelHashCalculator>();
|
|
mockHashFactory.Setup(f => f.Calculate(It.IsAny<DbCompiledModel>())).Returns("<Hash>");
|
|
|
|
Assert.Equal(
|
|
Strings.Database_NoDatabaseMetadata,
|
|
Assert.Throws<NotSupportedException>(
|
|
() => new ModelCompatibilityChecker().CompatibleWithModel(
|
|
mockInternalContext.Object,
|
|
mockHashFactory.Object,
|
|
throwIfNoMetadata: true)).Message);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TryGetModelHash tests
|
|
|
|
[Fact]
|
|
public void TryGetModelHash_throws_when_given_null_context()
|
|
{
|
|
#pragma warning disable 612,618
|
|
Assert.Equal("context", Assert.Throws<ArgumentNullException>(() => EdmMetadata.TryGetModelHash(null)).ParamName);
|
|
#pragma warning restore 612,618
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DatabaseCreator tests
|
|
|
|
[Fact]
|
|
public void Database_Create_calls_CreateDatabase_if_database_does_not_exist()
|
|
{
|
|
var mockOperations = new Mock<DatabaseOperations>();
|
|
var mockContext = new Mock<InternalContextForMock<FakeContext>>();
|
|
mockContext.Setup(m => m.DatabaseOperations).Returns(mockOperations.Object);
|
|
mockContext.Setup(m => m.CreateObjectContextForDdlOps()).Returns(new Mock<ClonedObjectContext>().Object);
|
|
mockOperations.Setup(m => m.Exists(null)).Returns(false);
|
|
|
|
mockContext.Object.Owner.Database.Create();
|
|
|
|
mockContext.Verify(m => m.CreateDatabase(null), Times.Once());
|
|
}
|
|
|
|
[Fact]
|
|
public void Database_CreateIfNotExists_calls_CreateDatabase_if_database_does_not_exist()
|
|
{
|
|
var mockOperations = new Mock<DatabaseOperations>();
|
|
var mockContext = new Mock<InternalContextForMock<FakeContext>>();
|
|
mockContext.Setup(m => m.DatabaseOperations).Returns(mockOperations.Object);
|
|
mockContext.Setup(m => m.CreateObjectContextForDdlOps()).Returns(new Mock<ClonedObjectContext>().Object);
|
|
mockOperations.Setup(m => m.Exists(null)).Returns(false);
|
|
|
|
mockContext.Object.Owner.Database.CreateIfNotExists();
|
|
|
|
mockContext.Verify(m => m.CreateDatabase(null), Times.Once());
|
|
}
|
|
|
|
[Fact]
|
|
public void Database_Create_throws_and_does_not_call_CreateDatabase_if_database_exists()
|
|
{
|
|
var mockOperations = new Mock<DatabaseOperations>();
|
|
var mockContext = new Mock<InternalContextForMock<FakeContext>>();
|
|
mockContext.Setup(m => m.DatabaseOperations).Returns(mockOperations.Object);
|
|
mockContext.Setup(m => m.CreateObjectContextForDdlOps()).Returns(new Mock<ClonedObjectContext>().Object);
|
|
mockContext.Setup(m => m.Connection).Returns(new SqlConnection("Database=Foo"));
|
|
mockOperations.Setup(m => m.Exists(null)).Returns(true);
|
|
|
|
Assert.Equal(
|
|
Strings.Database_DatabaseAlreadyExists("Foo"),
|
|
Assert.Throws<InvalidOperationException>(() => mockContext.Object.Owner.Database.Create()).Message);
|
|
|
|
mockContext.Verify(m => m.CreateDatabase(null), Times.Never());
|
|
}
|
|
|
|
[Fact]
|
|
public void Database_CreateIfNotExists_does_not_call_CreateDatabase_if_database_exists()
|
|
{
|
|
var mockOperations = new Mock<DatabaseOperations>();
|
|
var mockContext = new Mock<InternalContextForMock<FakeContext>>();
|
|
mockContext.Setup(m => m.DatabaseOperations).Returns(mockOperations.Object);
|
|
mockContext.Setup(m => m.CreateObjectContextForDdlOps()).Returns(new Mock<ClonedObjectContext>().Object);
|
|
mockOperations.Setup(m => m.Exists(null)).Returns(true);
|
|
|
|
mockContext.Object.Owner.Database.CreateIfNotExists();
|
|
|
|
mockContext.Verify(m => m.CreateDatabase(null), Times.Never());
|
|
}
|
|
|
|
public class FakeContext : DbContext
|
|
{
|
|
static FakeContext()
|
|
{
|
|
Database.SetInitializer<FakeContext>(null);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
[Fact]
|
|
public void Initializer_never_run_for_history_contexts()
|
|
{
|
|
var mockInitializer = new Mock<IDatabaseInitializer<HistoryContext>>();
|
|
Database.SetInitializer(mockInitializer.Object);
|
|
|
|
new HistoryContext().Database.Initialize(force: true);
|
|
mockInitializer.Verify(i => i.InitializeDatabase(It.IsAny<HistoryContext>()), Times.Never());
|
|
}
|
|
}
|
|
}
|