我正在使用与TeamCity、NUnit和Git的持续集成。我最近将双关语从FluentMigrator迁移到了实体框架迁移。我这样做主要是为了利用其中的脚手架功能。
但是,不需要先将更改放入迁移(假设应用程序在提交和推送提交之前没有运行),就有可能签入对源代码管理的某些更改。我使用的是预测试提交工作流,所以我希望在预测试中检测到这个问题,而不是等到调用migrate.exe (这在我的工作流程中太晚了,破坏了“绿色存储库”)。
我的问题是,如何创建一个单元/集成测试来检测迁移模型与上下文模型不匹配的情况,这样我就可以在尝试迁移之前失败构建?请注意,我希望它与数据库不匹配,并且不希望从测试中访问数据库。
我试过这种方法:
[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。希望他们会考虑增加一种方法来做到这一点。
发布于 2013-10-21 21:16:10
下面是一些代码,它将检查所有模型更改是否已经移植到迁移中。
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;
}发布于 2014-02-03 16:39:32
如果有人发现这一点有用,我将使用以下代码,通过在测试数据库上运行所有迁移来测试迁移:
[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");
}
}这将测试所有Up和Down迁移,以及在关闭自动迁移时检测挂起的更改。
注意:确保您在测试数据库上运行这个程序。在我的例子中,测试项目的app.config有到测试数据库的connectionString (只是一个本地SQLExpress实例)。
发布于 2017-03-07 08:48:00
到目前为止,我想得到最好的答案,所以我想出的是:
[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中指定一个仅用于测试项目的实体框架连接字符串,因为数据库将经常被删除和重新创建--如果在构建计算机上运行,请记住并行运行可能导致冲突,因此您可能希望在每个构建中更改字符串https://stackoverflow.com/questions/19284455
复制相似问题