Вы не можете - если модульное тестирование означает, что вы используете поддельный репозиторий в памяти, и поэтому используете LINQ для объектов. Если вы тестируете свои запросы с помощью LINQ to Objects, вы не тестировали свое приложение, а только ваш поддельный репозиторий.
Ваше исключение - это менее опасный случай, так как он указывает, что у вас есть красный тест, но, вероятно, фактически работающее приложение.
Более опасным является случай наоборот: наличие зеленого теста, но сбойное приложение или запросы, которые не возвращают те же результаты, что и ваш тест. Запросы, как ...
context.MyEntities.Where(e => MyBoolFunction(e)).ToList()
или
context.MyEntities.Select(e => new MyEntity { Name = e.Name }).ToList()
... будет работать нормально в тесте, но не с помощью LINQ к Entities в вашем приложении.
Запрос как ...
context.MyEntities.Where(e => e.Name == "abc").ToList()
... потенциально возвращать разные результаты с помощью LINQ к объектам, чем LINQ к Entities.
Вы можете проверить это и запрос в своем вопросе, построив интеграционные тесты, которые используют поставщик LINQ to Entities вашего приложения и реальную базу данных.
Редактировать
Если вы все еще хотите, чтобы писать тесты, я думаю, вы должны фальсифицировать сам или по крайней мере выражений в запросе запроса. Я мог себе представить, что что-то вдоль линий следующего кода может работать:
Создайте интерфейс для Where
выражения:
public interface IEntityExpressions
{
Expression<Func<MyEntity, bool>> GetSearchByDateExpression(DateTime date);
// maybe more expressions which use EntityFunctions or SqlFunctions
}
Создать реализацию для приложения ...
public class EntityExpressions : IEntityExpressions
{
public Expression<Func<MyEntity, bool>>
GetSearchByDateExpression(DateTime date)
{
return e => EntityFunctions.TruncateTime(e.Date) == date;
// Expression for LINQ to Entities, does not work with LINQ to Objects
}
}
...и второй реализации в тестовом модуле проекта:
public class FakeEntityExpressions : IEntityExpressions
{
public Expression<Func<MyEntity, bool>>
GetSearchByDateExpression(DateTime date)
{
return e => e.Date.Date == date;
// Expression for LINQ to Objects, does not work with LINQ to Entities
}
}
В классе, где вы используете запрос создать частный элемент этого интерфейса и два конструктора:
public class MyClass
{
private readonly IEntityExpressions _entityExpressions;
public MyClass()
{
_entityExpressions = new EntityExpressions(); // "poor man's IOC"
}
public MyClass(IEntityExpressions entityExpressions)
{
_entityExpressions = entityExpressions;
}
// just an example, I don't know how exactly the context of your query is
public IQueryable<MyEntity> BuildQuery(IQueryable<MyEntity> query,
SearchOptions searchOptions)
{
if (searchOptions.Date.HasValue)
query = query.Where(_entityExpressions.GetSearchByDateExpression(
searchOptions.Date));
return query;
}
}
Используйте первый (по умолчанию) конструктор в приложении:
var myClass = new MyClass();
var searchOptions = new SearchOptions { Date = DateTime.Now.Date };
var query = myClass.BuildQuery(context.MyEntities, searchOptions);
var result = query.ToList(); // this is LINQ to Entities, queries database
Используйте второй конструктор FakeEntityExpressions
в тестовом модуле:
IEntityExpressions entityExpressions = new FakeEntityExpressions();
var myClass = new MyClass(entityExpressions);
var searchOptions = new SearchOptions { Date = DateTime.Now.Date };
var fakeList = new List<MyEntity> { new MyEntity { ... }, ... };
var query = myClass.BuildQuery(fakeList.AsQueryable(), searchOptions);
var result = query.ToList(); // this is LINQ to Objects, queries in memory
Если вы используете контейнер инъекции зависимостей можно использовать его путем введения соответствующей реализации, если IEntityExpressions
в конструктор и не нужен конструктор по умолчанию.
Я проверил примерный код выше, и он сработал.
Я удалил свой ответ, это не было полезно для вас. Почему-то я подозревал, что не говорю вам ничего нового. Я понятия не имею, как обращаться с вашим запросом в модульном тесте, если не поставить весь запрос за интерфейс, который реализован в соответствии с LTO ('c => c.Date.Date == ...') в вашем модульном тесте , – Slauma
Не могли бы вы восстановить свой ответ? Я думаю, что это вполне справедливо и может помочь другим ... –
Метод - это только владелец места. Когда переводчик Linq to Entity обрабатывает дерево выражений, если видит этот метод, он знает, как заменить его конструкцией, специфичной для базы данных. Поэтому сам метод не имеет никакой реализации, но генерирует NotSupportedException. – Pawel