【问题标题】:Ignore Code first migrations for integration tests忽略集成测试的代码优先迁移
【发布时间】:2014-07-02 03:47:40
【问题描述】:

我想为我的EF code first 项目编写我的第一个集成测试,使用VS2013SqlServer CE,在我的测试项目中按照TestInitialize 方法定义,删除旧的测试数据库并重新创建一个新的数据库每次测试运行:

[TestInitialize]
public void SetupTest()
{
    // file path of the database to create
    var filePath = @"C:\code\TestingEf\TestTemp\RealMyAppDb.sdf";
    // delete it if it already exists
    if (File.Exists(filePath))
        File.Delete(filePath);

    // create the SQL CE connection string - this just points to the file path
    string connectionString = "Datasource = " + filePath;

    // NEED TO SET THIS TO MAKE DATABASE CREATION WORK WITH SQL CE!!!
    Database.DefaultConnectionFactory =
       new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");

    using (var context = new IASCoDbContext(connectionString,new DropCreateDatabaseAlways<IASCoDbContext>()))
        {
            // this will create the database with the schema from the Entity Model
            try
            {
                context.Database.Create();
            }
            catch
            {

            }
        }
        // initialise our DbContext class with the SQL CE connection string, 
        // ready for our tests to use it.
}

但是当代码到达context.Database.Create(); 行时,我得到以下错误:

{"指定的表不存在。[TableName]"} 我调试了一下测试,发现是因为程序要运行MigrationsUP()方法。

[更新]

以下代码包含我的IADCoDbContext 的构造函数:

public class IASCoDbContext : BaseDbContext
{
    static IASCoDbContext()
    {
        Database.SetInitializer<IASCoDbContext>(null);
    }

    public IASCoDbContext(string connectionString)
       : base("name=ERPContext")
    {
    }

    public IASCoDbContext(string connectionString, IDatabaseInitializer<IASCoDbContext> initializer)
        :base(connectionString)
    {

        Database.SetInitializer(initializer);
    }
    ...
}   

这是我的BaseDbContext:

public class BaseDbContext : DbContext
{
    public BaseDbContext()
        : base()
    {
    }

    public BaseDbContext(string context)
        : base(context)
    {

    }
}

我是否可以为我的集成测试禁用 Code First Migration

【问题讨论】:

    标签: c# entity-framework ef-code-first migration integration-testing


    【解决方案1】:

    通常,迁移由数据库初始化程序执行,可以通过将 DbContext 的初始化程序设置为 null 来禁用它。

    Database.SetInitializer<TestContext>(null);
    

    在不知道 IASCoDbContext 构造函数中的代码的情况下,我只能猜测发生了什么,但是

    DropCreateDatabaseAlways<IASCoDbContext>() 
    

    也是一个数据库初始化器,它基本上是这样做的

    public virtual void InitializeDatabase(TContext context)
    {
        Check.NotNull<TContext>(context, "context");
        context.Database.Delete();
        context.Database.Create(DatabaseExistenceState.DoesNotExist);
        this.Seed(context);
        context.SaveChanges();
    }
    

    我假设这个 InitializeDatabase 方法是在您的上下文的构造函数中调用的。 所以我认为

    context.Database.Create();
    

    方法调用是多余的。

    但正如我所说,在将 DatabaseInitializer 作为参数传递的情况下,上下文构造函数中发生了什么,这只是猜测。

    【讨论】:

    • 好吧,正如我所说,context.Database.Create 是多余的。只需使用没有初始化器 IASCoDbContext(string connectionString) 的 Context 构造函数,它应该可以工作。
    • 也许对你有用的信息是 context.Database.Create() 方法在可用时也使用迁移来创建数据库。
    • 你是对的,context.Database.Create() 在可用时使用迁移来创建数据库,我希望每次我的测试运行时删除并重新创建数据库而不使用迁移。如果我删除 context.Database.Create() 并使用没有初始化器的 Context 构造函数,我会收到此错误:{"The database file cannot be found. Check the path to the database. [ Data Source = C:\\code\\TestingEf\\TestTemp\\RealMyAppDb.sdf ]"}
    • 您不能同时删除两者。使用 DropCreateDatabaseAlways 初始化程序或 context.Database.Create() 方法。如果存在迁移,它们将用于创建数据库。做出此决定的所有代码都是内部代码。为什么不希望执行迁移?如果仅从模型创建数据库与迁移创建数据库相比,可能会有一些不同的行为。 (例如唯一索引,...)
    • 我在我的模型中重命名了一个列,当我运行我的测试时出现以下错误:“Assert.Fail failed.Error occurred in Db creationDirect column renaming is not supported by SQL Server Compact. To rename a SQL Server Compact 中的列,您将需要重新创建它。”
    猜你喜欢
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多