2011-06-21 28 views
8

在我的解决方案中,我有单元测试,它不依赖于数据库,而是具有外部依赖关系(如数据库)的嘲笑和集成测试。在使用LINQ到对象的单元测试中复制LINQ to Entities行为

当我使用mock进行单元测试时,使用了LINQ to Object。当集成测试或真正的程序运行时,使用LINQ to Entities,它比LINQ to Object更严格。

有没有办法在我的单元测试中复制LINQ To Object更严格的行为?

回答

6

当您的单元测试逻辑与EF提供的IQueryable一起工作时,您无法通过嘲讽EF来进行单元测试。这将始终导致从linq到实体切换到linq到对象。在简化的情况下,在单元测试中处理这个问题的正确方法是写一个假而不是模拟。假将模拟依赖关系的行为。在这种情况下,编写一个虚假的文件意味着编写内存中收集的EF提供程序的方式与实际提供程序与数据库一起工作的方式完全相同。写这样的提供者可能是项目本身。

因为一旦你的逻辑包含linq-to-entities查询,你应该总是用集成测试来测试它,或者重构代码以便查询本身在单独的方法中(由集成测试测试)并且以前的逻辑依赖于在EF本身上包含该方法的类 - 这会导致存储库模式,其中IQueryalbe未公开,但存储库公开了在某个实体上运行的每个所需查询的方法。我个人不喜欢这种类型的存储库。 Here is recent discussion关于不同的存储库实现。

如果您决定使用集成测试将数据库更改为内存,可以使用EFv4.1和代码优先,只需将连接字符串更改为SQL Compact 4即可使用(除非您使用某种特殊的直接SQL调用或在映射中要求一些特殊的SQL类型)。如果EF带有EDMX文件,它将不起作用,因为EDMX文件与确切的数据库版本紧密结合。有特殊的EDMX仅用于单元测试不是一种选择,因为你会再次测试不同的代码。

Here is set of related questions讨论单元测试EF代码和存储库带来的挑战。

0

您可以使用存储库模式来定义IRepository接口,在您的实际代码中,您可以使用Entity Framework来实现它,并且在您的单元测试中,可以使用模拟框架返回对象进行测试。

0

如果您希望对与数据库交谈的图层进行单元测试,以获得真实价值以及生产代码中的所有行为,则需要与数据库交谈。它可能被认为违反了单元测试中没有依赖关系的规则,但是没有其他方式让LINQ to Entities完成它的工作,而不是让它与数据库实现交谈。它可能(也可能应该)成为内存数据库 - 例如参见how is Ayende doing it