Как заставить генерацию запроса EF LINQ без выполнения - PullRequest
1 голос
/ 22 апреля 2011

У меня есть прекрасно отделенное приложение и приложение с зависимостями, которое использует Entity Framework 4.1 CodeFirst для предоставления IQueryable через шаблон репозитория. При тестировании клиентов репозитория достаточно легко смоделировать базовое хранилище данных, однако определенный класс ошибок не обнаруживается:

Клиенты репозитория могут свободно размещать свои собственные предикаты LINQ, объединения и т. Д. Поверх того, что возвращает репозиторий:

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

Этот тип запроса будет успешным в модульном тесте, который создает макет _myRepository, потому что mock возвращает коллекцию сущностей в памяти, а LINQ-to-Objects с радостью вызывает метод SomeMethod. Это не сработает с реальным хранилищем данных, потому что SomeMethod не переводится в SQL в LINQ-to-Entities.

Я пытаюсь найти способ, с помощью которого я мог бы и издеваться над набором данных, и заставить настоящий поставщик запросов EF генерировать (но не выполнять) SQL. Зачем? Потому что тесты должны быть быстрыми, и я не хочу, чтобы они били по реальной базе данных, если это вообще возможно. Генерация SQL избавит от проблем перевода, подобных этой.

До сих пор я не смог понять, как это сделать, потому что в моих модульных тестах я в конечном счете не контролирую, когда запрос материализуется. Я думаю, что мне нужно либо предоставить свою собственную версию IQueryable и различные методы расширения LINQ Queryable, либо попробовать подключиться через механизм провайдера (используя пример, полученный пару лет назад для провайдеров Caching / Tracing). это похоже на большую работу. Есть идеи, как этого добиться?

1 Ответ

5 голосов
/ 22 апреля 2011

Нет, сделать это невозможно - если только вы не собираетесь создавать своего собственного провайдера, который, в свою очередь, не является решением, потому что вы должны протестировать реальный провайдер, а не пользовательскую реализацию, которая не будет использоваться в реальном коде. Я обсуждал это здесь и здесь . Еще один связанный ответ о самом хранилище.

Просто вы не можете протестировать отображение и постоянство базы данных, не выполнив отображение и сохранение базы данных. Существует очень странное убеждение, что тестирование приложения означает написание модульных тестов. Это неправильное определение. Тестирование приложения означает, что написание тестов и модульных тестов - это только один из многих типов тестов, но они не могут тестировать все. Вам нужно объединить их с другими типами тестов. Правильным подходом для этого сценария могут быть интеграционные тесты, которые не нужно запускать каждый раз, но которые можно запланировать на сервере сборки.

...