本文介绍了如何强制EF LINQ查询生成而不执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很好的解耦应用程序和依赖注入的应用程序,它使用Entity Framework 4.1 CodeFirst通过存储库模式来公开IQueryable。在测试存储库客户端时,轻松地模拟底层数据存储区,但是某些类别的错误没有被捕获:



存储库客户端可以自由地层层自己的LINQ谓词,连接等等,最重要的是:

  {
_myRepository.FindAll()。Where x => x.Id == 3&& SomeMethod(x.Name)==Hello);
}

这种查询将在单元测试中成功,嘲笑_myRepository,因为mock返回实体的内存集合,LINQ到对象很乐意调用方法SomeMethod。它将对真正的数据存储失败,因为SomeMethod不会转换为LINQ到实体中的SQL。



我试图找出一种方法我可以模拟数据集,并导致真正的EF查询提供程序生成(但不执行)SQL。为什么?因为测试应该是快速的,如果可能的话我不希望他们打到一个真正的数据库。生成SQL将冲出这样的翻译问题。



到目前为止,我还没有弄清楚如何做到这一点,因为在我的单元测试中,我是最终不能控制查询何时实现。我想我需要提供我自己的IQueryable版本和各种LINQ Queryable扩展方法,或者通过提供者机制(使用几年前的缓存/跟踪提供程序的示例)来尝试和挂接。这些看起来好像很多工作。任何关于如何实现这一点的想法?

解决方案

没有办法没有办法 - 除非你要建立自己的提供者而不是解决方案,因为您必须测试真正的提供商而不是在实际代码中不会使用的自定义实现。我讨论过和。 关于存储库本身。



只要您无需测试数据库映射和持久性,而不进行数据库映射和持久性。有一些非常奇怪的信念,测试应用意味着写单元测试。这是错误的定义。测试应用程序意味着编写测试和单元测试只是许多测试类型之一,但它们无法测试所有内容。您需要将它们与其他类型的测试相结合。这种情况的正确方法可以是集成测试,不需要每次运行,而是可以在构建服务器上进行调度。


I have a nicely decoupled app and dependency-injected app that uses Entity Framework 4.1 CodeFirst to expose IQueryable through a repository pattern. It's easy enough to mock the underlying datastore when testing the repository clients, however a certain class of bug is not being caught:

The repository clients are free to layer their own LINQ predicates, joins, etc on top of what the repository returns:

{
     _myRepository.FindAll().Where( x => x.Id == 3 && SomeMethod(x.Name) == "Hello" );
}

This kind of query will succeed in a unit test that mocks _myRepository, because mock returns an in-memory collection of entities and LINQ-to-Objects is happy to call the method "SomeMethod". It will fail against the real data-store because "SomeMethod" does not translate to SQL in LINQ-to-Entities.

I'm trying to figure out a way that I can both mock the dataset and cause the real EF query provider to generate (but not execute) the SQL. Why? Because the tests are supposed to be fast and I don't want them hitting a real database if at all possible. Generating the SQL will flush out translation issues like this.

So far, I have not been able to figure out how to do this, because in my unit tests, I am ultimately not in control of when the query gets materialized. I'm thinking I need to either provide my own version of IQueryable and the various LINQ Queryable extension methods or try and hook in via the provider mechanism (using the sample from a couple of years ago that does Caching/Tracing providers.) Both of these seem like a lot of work. Any ideas on how to achieve this?

解决方案

No there is no way to do that - unless you are going to build your own provider which in turn is not the solution because you must test the real provider not a custom implementation which will not be used in the real code. I discussed it here and here. One more related answer about repository itself.

Simply you can't test database mapping and persistence without doing database mapping and persistence. There is some very strange belief that testing application means writing unit tests. That is wrong definition. Testing application means writing tests and unit tests are just one of many test types but they can't test everything. You need to combine them with other types of tests. The correct approach for this scenario can be integration tests which doesn't have to run every time but can be scheduled on the build server.

这篇关于如何强制EF LINQ查询生成而不执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-27 22:42