// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. namespace System.Data.Entity { using System.Data.Entity.Core.Objects; using System.Data.Entity.Internal; using System.Data.Entity.Resources; using System.Text; using Moq; using Moq.Protected; /// /// Helper class that uses Moq to create mocks for the InternalContext and related classes such /// that different database initialization strategies can be tested and the operations that these /// strategies perform can be recorded and validated. /// public class DatabaseInitializerTracker where TInitializer : class, IDatabaseInitializer where TContext : DbContext, new() { private readonly StringBuilder _operations = new StringBuilder(); private readonly Mock> _mockInternalContext; private readonly Mock _mockDatabaseOps; private readonly Mock _mockDbContext; private readonly Mock _mockStrategy; private bool _databaseExists; public DatabaseInitializerTracker(bool databaseExists, bool modelCompatible = true, bool hasMetadata = true) { _databaseExists = databaseExists; _mockInternalContext = new Mock> { CallBase = true }; _mockDatabaseOps = new Mock(); _mockDbContext = Mock.Get((TContext)_mockInternalContext.Object.Owner); _mockInternalContext.Setup(c => c.DatabaseOperations).Returns(_mockDatabaseOps.Object); _mockInternalContext.Setup(c => c.DefaultInitializer).Returns(new CreateDatabaseIfNotExists()); _mockInternalContext.Setup(c => c.CreateDatabase(It.IsAny())).Callback( () => { _databaseExists = true; _operations.Append("CreateDatabase "); }); _mockDatabaseOps.Setup(d => d.Create(It.IsAny())).Callback( () => { _databaseExists = true; _operations.Append("Create "); }); _mockDatabaseOps.Setup(d => d.Exists(It.IsAny())).Callback(() => _operations.Append("Exists ")).Returns( DatabaseExists); _mockDatabaseOps.Setup(d => d.DeleteIfExists(It.IsAny())).Callback(() => _operations.Append("DeleteIfExists ")). Returns(DeleteIfExists); _mockInternalContext.Setup(c => c.UseTempObjectContext()).Callback(() => _operations.Append("UseTempObjectContext ")); _mockInternalContext.Setup(c => c.DisposeTempObjectContext()).Callback(() => _operations.Append("DisposeTempObjectContext ")); _mockInternalContext.Setup(c => c.SaveMetadataToDatabase()).Callback(() => _operations.Append("SaveMetadataToDatabase ")); _mockInternalContext.Setup(c => c.CompatibleWithModel(It.IsAny())).Callback( (bool throwIfNoMetadata) => { if (!hasMetadata && throwIfNoMetadata) { throw Error.Database_NoDatabaseMetadata(); } }).Returns(modelCompatible); _mockInternalContext.Setup(c => c.CreateObjectContextForDdlOps()).Returns(new Mock().Object); _mockInternalContext.SetupGet(c => c.ProviderName).Returns("Dummy.Data.Provider"); _mockStrategy = new Mock { CallBase = true }; _mockStrategy.Protected().Setup("Seed", ItExpr.IsAny()).Callback(() => _operations.Append("Seed ")); } private bool DeleteIfExists() { var exists = _databaseExists; _databaseExists = false; return exists; } private bool DatabaseExists() { return _databaseExists; } public void ExecuteStrategy() { _mockStrategy.Object.InitializeDatabase(_mockDbContext.Object); } public void RegisterStrategy() { var mockContextType = _mockDbContext.Object.GetType(); var initMethod = typeof(Database).GetMethod("SetInitializer").MakeGenericMethod(mockContextType); initMethod.Invoke(null, new object[] { _mockStrategy.Object }); } public string Result { get { return _operations.ToString().Trim(); } } public TContext Context { get { return _mockDbContext.Object; } } internal Mock> MockInternalContext { get { return _mockInternalContext; } } } }