Unit-тестирование кода с CreateSourceQuery

63 views
Skip to first unread message

Michael Bashurov

unread,
Dec 23, 2015, 10:11:04 AM12/23/15
to dotnetconf
Ситуация такая
EntityFramework 5, Database First
Есть сущность, в ней есть метод которой использует CreateSourceQuery

public class Entity1
{
 
public EntityCollection<Entity2> Entities2 { get; set; }

 
public Entity2 GetEntity2(Guid id)
 
{
   
return
Entities2.CreateSourceQuery().Single(x => x.ID == id);
 
}
}

Если что, CreateSourceQuery это такой особенный метод EF-а, который позволяет из EntityCollection сделать IQueryable
Ибо если этого не сделать то все попытки вызвать какой-то linq по такой коллекции благополучно загрузят всё в память, что, ясное дело, может быть чревато

И в общем то все бы ничего, но когда пытаешься протестировать этот метод, не используя всякие штуки типа Effort (In-memory db для EF), а сказав 

Entities2 = new EntityCollection<Entity2>() { new Entity2(), ... };

то CreateSourceQuery возвращает null и наш тест благополучно валится

в ответе прямо намекают что это должен быть скорее интеграционный тест нежели юнит, но меня в данном случае интересует только юнит-тесты
я решил этот вопрос так: заменил использование CreateSourceQuery на собственный метод GetQueryable и в конфигурации ioc контейнера для тестов устанавливаю значение IsTests в true,
надеясь на то что это произойдёт раньше вызова GetQueryable 

public static class CreateSourceQueryHack
{
  public bool IsTests { get; set; }
 
  public static IQueryable<T> GetQueryable<T>(this EntityCollection<T> entityCollection) where T : class
  {
    if (IsTests)
    {
      return entityCollection.AsQueryable();
    }
       else
    {
      return entityCollection.CreateSourceQuery();
    }
  }
}

Проблемы вижу две:
Соглашение о неиспользовании CreateSourceQuery
Соглашение об установке IsTests

Хочется узнать какие еще могут быть проблемы и как можно по-другому это дело решить?

Oleg Karpov

unread,
Dec 24, 2015, 2:46:33 AM12/24/15
to dotne...@googlegroups.com
1. Сущность, имеющая тип, связанный с EntityCollection по умолчанию является зависимой от EF. Зачем ее тестировать отдельно?
2. Действительно ли речь идет о DbContext и DB First? Если это так, то, видимо, есть проблема с реализацией DB контекста в проекте.
3. В отрыве от этого примера: статический класс, подменяющий поведение - это совсем плохо. Не проще локализовать вызов и использовать virtual?

--

---
Вы получили это сообщение, поскольку подписаны на группу "dotnetconf".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес dotnetconf+...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Чапаев

unread,
Dec 25, 2015, 6:54:37 AM12/25/15
to dotnetconf
вот пара ссылок кажется по этой теме. 
 
но решение выглядит  неудачным, так как оно слишком жестко связанное - и использованием конкретных классов и соглашений.
возможно переделать архитектуру запроса - использовать патерн query object.
вот тут 
как то мы общими усилиями придумали реализацию под linq - запрос получается полностью тестируемым.
можно адаптировать под EF.
по патерну можно почитать у Александра.

Michael Bashurov

unread,
Jan 21, 2016, 1:18:22 PM1/21/16
to dotnetconf
>>1. Сущность, имеющая тип, связанный с EntityCollection по умолчанию является зависимой от EF. Зачем ее тестировать отдельно?
пытаюсь выиграть в скорости, даже если использовать Effort — тесты получаются очень медленными

>>Действительно ли речь идет о DbContext и DB First? Если это так, то, видимо, есть проблема с реализацией DB контекста в проекте.
а я не говорил что это DbContext, это ObjectContext

>>В отрыве от этого примера: статический класс, подменяющий поведение - это совсем плохо. Не проще локализовать вызов и использовать virtual?
типа сделать стратегию которая превращает EntityCollection в IQueryable?
пропадет удобство метода расширения, но это можно потерпеть
если сущности не резолвятся, инжектить придется руками
ну да в общем то

четверг, 24 декабря 2015 г., 10:46:33 UTC+3 пользователь Oleg Karpov написал:
Reply all
Reply to author
Forward
0 new messages