【发布时间】:2011-01-13 03:16:07
【问题描述】:
由于 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 来回发送一些电子邮件后,发现
TransactionScopes 现在可以在 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!
}
}
【问题讨论】:
-
当然 SQL CE 支持事务...但是使用 TransactionScope 是一种非常错误的做法。只需通过 Connection 对象正常执行即可。
-
我不确定在没有
TransactionScope的情况下如何处理 EF4 实体,除非您的意思是不调用SaveChanges(),这意味着测试不是有效的测试。 -
您能否举例说明如何使用 Sql CE 播种数据?我使用 EF6 并想使用 sql ce 测试它
标签: c# unit-testing entity-framework-4 functional-testing sql-server-ce