已编辑
我正在为数据库初始化方法运行单元测试(使用 nunit)。我设置了测试并使用以下测试示例为数据库播种:
[TestFixtureSetUp]
public void SetUp()
{
//select database
Database.DefaultConnectionFactory = new SqlConnectionFactory(connectionString);
database = new POSDatabaseContext(connectionString);
//drop database and recreate
string query = "ALTER DATABASE [POS] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;";
database.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, query);
database.Database.Delete();
database.Database.Create();
//add seed value to test against
database.Metadata.Add(new Metadata {
ID = "META",
IsInitialized = false,
testBool = true,
TimeCreated = DateTime.Now,
TimeEdited = DateTime.Now
});
database.SaveChanges();
}
然后我运行这个测试方法:
[Test]
public void InitializeDatabaseTestWithMatchingModel()
{
//set initializer for data context to test it, and run it
Database.SetInitializer<POSDatabaseContext>(new
CustomDropCreateDatabaseWithMatchingModelTest());
database.Database.Initialize(true);
//use the metadata table to check if it was run correctly
//if metadata exist, which it should
if(database.Metadata.Any(s => s.ID == "META"))
{
Metadata actual = database.Metadata.Single(s => s.ID == "META");
Assert.IsTrue(actual.IsInitialized);
}
else
throw new Exception("The Database was not seeded correctly for the test");
}
为了测试我的自定义 Initializer,我创建了一个继承自它的类,我可以使用 Seed() 方法生成一些我可以测试的数据。这是类:
//class is derived from class that needs to be tested so can still be used for testing
//this class adds seed data to check the database with
public class CustomDropCreateDatabaseWithMatchingModelTest
: CustomDropCreateDatabaseIfModelChanges<POSDatabaseContext>
{
protected override void Seed(POSDatabaseContext context)
{
//if metadata exist (Which it should since the database
//shouldn't be dropped because the model is the same)
if(context.Metadata.Any(s => s.ID == "META"))
{
Metadata meta = context.Metadata.Single(s => s.ID == "META");
if(meta.IsInitialized == true)
throw new Exception("The database has not been dropped"+
" and recreated correctly during the unit test setup."
);
else
{
meta.IsInitialized = true;
meta.TimeEdited = DateTime.Now;
context.SaveChanges();
}
}
else
throw new Exception("Metadata not found. The database was"+
" either dropped because it was falsely accused of not"+
" having a matching model, OR the database was not seeded"+
" properly during unit test setup."
);
}
}
它派生的类:
//This file contains custom versions of the built in
//database intializer classes in which an SQL Statement
//is run to stop all connections to the database so that
//when the database is dropped, a database in use
//exception is not thrown.
public class CustomDropCreateDatabaseIfModelChanges<Context>
: IDatabaseInitializer<Context> where Context : DbContext
{
public void InitializeDatabase(Context context)
{
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(true))
{
string query = "ALTER DATABASE [POS] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;";
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, query);
context.Database.Delete();
context.Database.Create();
}
//else do nothing and continue
}
else context.Database.Create();
//run seed method
Seed(context);
}
//OVERIDE ME
//this method seeds the database with data
protected virtual void Seed(Context context) { }
}
我似乎遇到的问题是初始化直到断言之后才运行。我已经检查了 Metadata actual 的值,这些值是来自 SetUp() 方法的值。我还检查了在我正在测试的方法中调用 SaveChanges() 之前对象是否被标记为已修改。但是,该方法肯定正在运行,因为数据库反射(reflect)了该方法的值。
我认为我遇到的最初问题是 IsInitialized 属性作为错误值返回,因为它在数据库中为 1,但我在代码中得到了 false。
最佳答案
将 Assert.AreEqual(true,
更改为 Assert.IsTrue(
,因为 true
可以在类型之间有不同的形式。如您所见,它在数据库中编码为 1
,可能不完全匹配。
您可以检查 SaveChanges()
是否正确更新断言之前的上下文:首先对 TimeEdited
执行断言。 (首先将 DateTime.Now 替换为一些更容易比较的常量值)。
关于c# - 数据库初始化运行太晚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25935967/