在我的解决方案中,我有单元测试,它不依赖于数据库,而是具有外部依赖性(如数据库)的模拟和集成测试。
当我使用模拟进行单元测试时,使用LINQ to Object。当集成测试或实际程序运行时,使用LINQ to Entities,它比LINQ to Object更严格。
有没有办法在单元测试中复制LINQ To Object更严格的行为?
答案 0 :(得分:6)
一旦您的单元测试逻辑与EF提供的IQueryable
一起工作,您就无法通过模拟EF来进行单元测试。这将始终导致从linq到实体切换到linq到对象。在简化的情况下,在单元测试中处理此问题的正确方法是写假而不是模拟。假将模拟依赖的行为。在这种情况下,编写伪造意味着编写EF提供程序在内存中进行处理,其方式与实际提供程序与数据库一起工作的方式完全相同。编写这样的提供者可能是项目本身。
因此,一旦你的逻辑包含linq-to-entities查询,你应该总是使用集成测试对其进行测试,或者重构代码,以便查询本身处于单独的方法中(通过集成测试进行测试),而以前的逻辑现在依赖于包含该方法的类而不是EF本身 - 这导致存储库模式,其中IQueryalbe
未公开,但存储库公开了在某个实体上运行的每个所需查询的方法。我个人不喜欢这种存储库。 Here is recent discussion关于不同的存储库实现。
如果您决定使用集成测试将数据库更改为内存,则可以使用EFv4.1和代码,只需将连接字符串更改为SQL Compact 4,它就可以工作(除非您使用一些特殊的直接SQL在映射中调用或要求一些特殊的SQL类型)。对于带有EDMX文件的EF,它将无法工作,因为EDMX文件与精确的数据库版本紧密耦合。对于单元测试而言,使用特殊的EDMX不是一种选择,因为您将再次测试不同的代码。
Here is set of related questions讨论单元测试EF代码和存储库的挑战。
答案 1 :(得分:0)
您可以使用存储库模式来定义IRepository接口,在您的实际代码中,您可以使用Entity Framework实现它,并且在您的单元测试中,您可以使用模拟框架返回对象进行测试。
答案 2 :(得分:0)
如果您希望与数据库对话的图层的单元测试具有真实价值和生产代码中的所有行为,则需要与数据库进行通信。它可能被认为打破了在单元测试中没有依赖关系的规则,但没有其他方法让LINQ to Entities完成其工作而不是让它与真正的数据库交谈。它可能(也可能应该)是内存数据库 - 例如参见how is Ayende doing it。