由于 Linq-to-Entities (EF4) 和 Linq-to-Objects 之间的潜在差异,我需要使用实际的数据库来确保我的查询类正确地从 EF 检索数据。 Sql CE 4 似乎是完美的工具,但是我遇到了一些小问题。这些测试使用的是 MsTest。
我遇到的问题是,如果数据库没有被重新创建(由于模型更改),数据会在每次测试后不断添加到数据库中,而不会删除数据。这可能会导致测试冲突,查询返回的数据多于预期。
我的第一个想法是在 TestInitialize
方法中初始化一个 TransactionScope
,并在 TestCleanup
中处理事务。不幸的是,Sql CE4 不支持事务。
我的下一个想法是通过 File.Delete()
调用删除 TestCleanup
中的数据库。不幸的是,这似乎在第一个测试运行后不起作用,因为第一个测试的 TestCleanup
似乎删除了数据库,但是第一个测试之后的每个测试似乎都没有重新创建数据库,因此它给出了找不到数据库文件的错误。
我试图将测试类的 TestInitialize
和 TestCleanup
标记更改为 ClassInitialize
和 ClassCleanup
,但是由于在 ClassInitialize
之前运行的测试,出现了 NullReferenceException
错误(或者看起来是这样。ClassInitialize
在基类中,所以这可能是它的原因).
我已经用尽了有效使用 Sql CE4 进行测试的方法。有没有人有更好的想法?
编辑: 我最终想出了一个解决方案。在我的 EF 单元测试基类中,我启动了我的数据上下文的一个新实例,然后调用
context.Database.Delete()
和 context.Database.Create()
。单元测试运行速度稍慢,但现在我可以使用真实数据库进行有效的单元测试
最终编辑: 在与 Microsoft 来回发送一些电子邮件后,发现
TransactionScope
现在允许在 SqlCE 中使用最新版本的 SqlCE。但是,如果您使用的是 EF4,则存在一些限制,因为您必须在开始事务之前显式打开数据库连接。以下代码展示了如何成功使用 Sql CE 进行单元/功能测试的示例:
[TestMethod]
public void My_SqlCeScenario ()
{
using (var context = new MySQLCeModelContext()) //ß derived from DbContext
{
ObjectContext objctx = ((IObjectContextAdapter)context).ObjectContext;
objctx.Connection.Open(); //ß Open your connection explicitly
using (TransactionScope tx = new TransactionScope())
{
var product = new Product() { Name = "Vegemite" };
context.Products.Add(product);
context.SaveChanges();
}
objctx.Connection.Close(); //ß close it when done!
}
}
最佳答案
在您的 TestInitialize
中,您应该执行以下操作:
System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
new System.Data.Entity.Database.DropCreateDatabaseAlways<YourEntityFrameworkClass>());
这将导致 Entity Framework 在测试运行时始终重新创建数据库。
顺便说一句,您可以创建一个继承自 DropCreateDatabaseAlways
的替代类。这将允许您每次都使用设置的数据为您的数据库做种。
public class DataContextInitializer : DropCreateDatabaseAlways<YourEntityFrameworkClass> {
protected override void Seed(DataContext context) {
context.Users.Add(new User() { Name = "Test User 1", Email = "test@test.com" });
context.SaveChanges();
}
}
然后在您的 Initialize 中将调用更改为:
System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
new DataContextInitializer());
关于c# - 如何使用 Sql CE 4 数据库进行功能测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4676460/