EDITED
我正在运行单元测试(使用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");
}
为了测试我的自定义初始化程序,我创建了一个继承自它的类,我可以使用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) { }
}
我似乎遇到的问题是,在断言之后,Initilization才会运行。我检查了元数据实际的值,值是SetUp()方法的值。我还检查了在我测试的方法中调用SaveChanges()之前对象被标记为已修改。但是,该方法肯定是在运行,因为数据库反映了方法的值。
我认为我遇到的原始问题是IsInitialized属性被返回为错误值,因为它在数据库中为1,但我在代码中得到了错误。
答案 0 :(得分:1)
将Assert.AreEqual(true,
更改为Assert.IsTrue(
,因为true
类型之间可以有不同的格式。正如您所注意到的,它在数据库中编码为1
,可能不完全匹配。
您可以检查SaveChanges()
是否正确更新Assert之前的上下文:首先在TimeEdited
上执行断言。 (将DateTime.Now替换为一些更容易比较的常量值。)
答案 1 :(得分:0)
在我的测试课程的顶部,我有:
[TestFixture]
public class CustomDropCreateDatabaseIfModelChangesTest
{
protected const string connectionString =
"Data Source=SABERTOOTH\\POS;Initial Catalog=POS;Integrated Security=true;Pooling=false";
protected POSDatabaseContext database;
....
}
我已经更改了测试以使用新的DbContext:
[Test]
public void InitializeDatabaseTestWithMatchingModel()
{
//set initializer for data context to test it, and run it
Database.SetInitializer<POSDatabaseContext>(new CustomDropCreateDatabaseWithMatchingModelTest());
database.Database.Initialize(true);
POSDatabaseContext newContext = new POSDatabaseContext(connectionString);
//use the metata table to check if it was run correctly
//if metadata exist, which it should
if(newContext.Metadata.Any(s => s.ID == "META"))
{
Metadata actual = newContext.Metadata.Single(s => s.ID == "META");
Assert.IsTrue(actual.IsInitialized);
}
else
throw new Exception("The Database was not seeded correctly");
}
事实证明,Pieter21是正确的,因为某些原因,上下文没有得到刷新,并且必须创建新的上下文。但我不确定为什么。