首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架迁移-如何创建单元测试以确保迁移模型是最新的?

实体框架迁移-如何创建单元测试以确保迁移模型是最新的?
EN

Stack Overflow用户
提问于 2013-10-09 23:17:57
回答 5查看 9K关注 0票数 14

我正在使用与TeamCity、NUnit和Git的持续集成。我最近将双关语从FluentMigrator迁移到了实体框架迁移。我这样做主要是为了利用其中的脚手架功能。

但是,不需要先将更改放入迁移(假设应用程序在提交和推送提交之前没有运行),就有可能签入对源代码管理的某些更改。我使用的是预测试提交工作流,所以我希望在预测试中检测到这个问题,而不是等到调用migrate.exe (这在我的工作流程中太晚了,破坏了“绿色存储库”)。

我的问题是,如何创建一个单元/集成测试来检测迁移模型与上下文模型不匹配的情况,这样我就可以在尝试迁移之前失败构建?请注意,我希望它与数据库不匹配,并且不希望从测试中访问数据库。

我试过这种方法:

代码语言:javascript
复制
    [Test]
    public void CheckWhetherEntityFrameworkMigrationsContextIsUpToDate()
    {
        Assert.DoesNotThrow(() =>
        {
            CallDatabase();
        });

    }

    private void CallDatabase()
    {
        using (var ctx = new MyContext("SERVER=(local);DATABASE=MyDatabase;Integrated Security=True;"))
        {
            var tenant = (from t in ctx.Tenant
                          select t).FirstOrDefault();
        }
    }

但是,当存在挂起的迁移时(而不仅仅是在迁移模型与上下文模型不同步的情况下,这是我所追求的),这总是失败的。

更新

为此,我在工作项项目上添加了一个EntityFramework。希望他们会考虑增加一种方法来做到这一点。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-10-21 21:16:10

下面是一些代码,它将检查所有模型更改是否已经移植到迁移中。

代码语言:javascript
复制
bool HasPendingModelChanges()
{
    // NOTE: Using MigratorScriptingDecorator so changes won't be made to the database
    var migrationsConfiguration = new Migrations.Configuration();
    var migrator = new DbMigrator(migrationsConfiguration);
    var scriptingMigrator = new MigratorScriptingDecorator(migrator);

    try
    {
        // NOTE: Using InitialDatabase so history won't be read from the database
        scriptingMigrator.ScriptUpdate(DbMigrator.InitialDatabase, null);
    }
    catch (AutomaticMigrationsDisabledException)
    {
        return true;
    }

    return false;
}
票数 7
EN

Stack Overflow用户

发布于 2014-02-03 16:39:32

如果有人发现这一点有用,我将使用以下代码,通过在测试数据库上运行所有迁移来测试迁移:

代码语言:javascript
复制
[TestClass]
public class MigrationsTests
{
    [TestMethod]
    public void RunAll()
    {
        var configuration = new Configuration();
        var migrator = new DbMigrator(configuration);
        // back to 0
        migrator.Update("0");
        // up to current
        migrator.Update();
        // back to 0
        migrator.Update("0");
    }
}

这将测试所有UpDown迁移,以及在关闭自动迁移时检测挂起的更改。

注意:确保您在测试数据库上运行这个程序。在我的例子中,测试项目的app.config有到测试数据库的connectionString (只是一个本地SQLExpress实例)。

票数 11
EN

Stack Overflow用户

发布于 2017-03-07 08:48:00

到目前为止,我想得到最好的答案,所以我想出的是:

代码语言:javascript
复制
[TestClass()]
public class MigrationsTests
{
    [TestMethod()]
    public void MigrationsUpDownTest()
    {
        // Unit tests don't have a DataDirectory by default to store DB in
        AppDomain.CurrentDomain.SetData("DataDirectory", System.IO.Directory.GetCurrentDirectory());

        // Drop and recreate database
        BoxContext db = new BoxContext();
        db.Database.Delete();

        var configuration = new Migrations.Configuration();
        var migrator = new DbMigrator(configuration);

        // Retrieve migrations
        List<string> migrations = new List<string>;
        migrations.AddRange(migrator.GetLocalMigrations());

        try
        {
            for (int index = 0; index < migrations.Count; index++)
            {
                migrator.Update(migrations[index]);
                if (index > 0) {
                    migrator.Update(migrations[index - 1]);
                } else {
                    migrator.Update("0"); //special case to revert initial migration
                }
            }

            migrator.Update(migrations.Last());
        }
        catch (SqlException ex)
        {
            Assert.Fail("Should not have any errors when running migrations up and down: " + ex.Errors[0].Message.ToString());
        }

        // Optional: delete database
        db.Database.Delete();
    }

    [TestMethod()]
    public void PendingModelChangesTest()
    {
        // NOTE: Using MigratorScriptingDecorator so changes won't be made to the database
        var migrationsConfiguration = new Migrations.Configuration();
        var migrator = new DbMigrator(migrationsConfiguration);
        var scriptingMigrator = new MigratorScriptingDecorator(migrator);

        try
        {
            // NOTE: Using InitialDatabase so history won't be read from the database
            scriptingMigrator.ScriptUpdate(DbMigrator.InitialDatabase, null);
        }
        catch (AutomaticMigrationsDisabledException)
        {
            Assert.Fail("Should be no pending model changes/migrations should cover all model changes.");
        }
    }
}

有几件事值得注意:

  • 您需要在测试项目中安装实体框架
  • 您需要将[assembly: InternalsVisibleTo("MyTestsProject")]添加到Configuration类的顶部
  • 您需要在App.config中指定一个仅用于测试项目的实体框架连接字符串,因为数据库将经常被删除和重新创建--如果在构建计算机上运行,请记住并行运行可能导致冲突,因此您可能希望在每个构建中更改字符串
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19284455

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档