我正在尝试首先使用EntityFramework代码测试我的代码。为了使其可测试并允许隔离测试,我创建了一个我的DbContext
实现的接口。我没有测试DbContext
类 - 我将假设EF代码按预期工作。
现在,请考虑以下方法:
public IEnumerable<User> GetOddId()
{
return context_.Users.Where((u, i) => i % 2 == 1).AsEnumerable();
}
此方法将通过我的模拟FakeDbSet
传递(因为它将使用内存中的LINQ提供程序),而在使用EF / LINQ to SQL驱动程序时,它会因异常而失败。
你会保持原样并希望人们知道不要写这样的问题吗?你会放弃隔离测试并测试实际的数据库吗?
带有DataMigrations的LocalDb(可能带有适当的种子)是否有助于对实际数据库进行测试?
请证明答案是合理的。
TLDR:如何测试EntityFramework代码,考虑内存LINQ和SQL LINQ之间的差异?
很久以后编辑:我已经找到了一个非常好的框架,完全符合我的需要。我写了一篇关于unit testing with Effort的博文。另请注意,即将推出的EF6可能不需要这一切,它承诺提供一些单元测试功能。
答案 0 :(得分:8)
为此,我们使用SQLite的内存数据库。它们可以非常快速地创建,查询和拆除,并且几乎不会对整体测试速度产生任何影响。一旦你为自己设置了一个测试框架来创建数据库并注入数据,就可以快速编写测试。
当然,SQLite是一个比大多数人简单得多的数据库,因此复杂的查询可能无法转换为其SQL版本,但是为了测试90%的情况,它运行良好。
这些测试是否构成集成测试?我不这么认为。他们仍然只测试一个你的代码单元,即生成LINQ查询的位。您正在测试两件事: 1)查询返回正确的数据(但您可以使用内容集合检查此内容),并且 2)可以通过Entity Framework将查询转换为有效的SQL。测试后者的唯一真正方法是在真实的实体框架中激活查询,但使用 stubbed 数据库。
虽然您可能认为真正的单元测试应该仅测试代码的输出(即解析并检查已生成的表达式树),以及更难编写,但它并不能真正证明任何东西。例如,如果您修改代码以生成内部联接而不是子查询,您是否希望测试中断?只有当它返回不同的结果时,我才会想到。
答案 1 :(得分:1)
在我工作的地方,我们有一个dev / beta / production SQL服务器。有时我们会在对实际数据库执行测试之前,针对beta和种子测试数据(例如在测试特定选择之前插入等)创建测试。人们会区分单元测试和集成测试,但它至少让我们测试我们的逻辑,这比仅仅交叉手指更好,希望在数据访问层最好。
内存提供商有什么用,它很容易测试但在某些重要情况下实际上并不代表实时系统?
编辑:我们不使用EF,顺便说一句......
答案 2 :(得分:0)