Как мне издеваться над IQueryable <T> - PullRequest
34 голосов
/ 11 февраля 2010

Я создаю репозиторий, который предоставляет IQueryable. Какой лучший способ сделать это для моего юнит-тестирования?

Поскольку я использую RhinoMocks для остальных моих фиктивных объектов, я попытался сделать следующее:

IQueryable<MyObject> QueryObject = 
    MockRepository.GenerateStub<IQueryable<MyObject>>();

Хотя это не работает, поэтому я попытался сделать это:

IQueryable<MyObject> QueryObject = 
    (new List<MyObject> { new MyObject() }).AsQueryable();

Есть ли лучший способ сделать это, или в каких-либо других фреймворках встроена поддержка IQueryable?

Мой интерфейс репозитория выглядит так:

public interface IRepository<T> where T : TableServiceEntity
{
    IQueryable<T> Table { get; }
    void Attach(T existingItem);
    void Delete(T itemToDelete);
    void Insert(T newItem);
    T Load(string partitionKey, string rowKey);
    IEnumerable<T> Load(string partitionKey);
    IEnumerable<T> Query(IQueryable<T> query);
    IEnumerable<T> Last(int count);
    T Last();
    void Update(T item);
}

Вот метод, который я хочу проверить:

public Post LoadPost(int year, int month, int day, string slug)
{
    var query = from p in _blogRepository.Table
                where 
                    p.PartitionKey == Key.Partition(year, month, day) 
                    && p.Slug == slug
                select p;

    var posts = _blogRepository.Query(query.Take(1));

    return posts.First();
}

Тогда вот тест, как он у меня есть, который будет проверять LoadPost.

[Fact]
public void LoadWillRetrieveByPartitionKeyAndRowKeyWhenUsingUriFormat()
{
    Repository
        .Stub(x => x.Query(Arg<IQueryable<Post>>.Is.Anything))
        .Return(new List<Post> {_post});

    var result = Service.LoadPost(
                            _post.Year(),
                            _post.Month(), 
                            _post.Day(), 
                            _post.Slug);

    Assert.NotNull(result);
}

Код взят из моего проекта AzureBlog .

Ответы [ 4 ]

10 голосов
/ 12 февраля 2010

Я обычно делаю именно то, что вы в итоге сделали в своем тесте. При написании моих тестов я предполагаю, что классы библиотеки .Net работают правильно и не содержат ошибок, поэтому я могу использовать их в тестах. Когда мне нужен список тестов, набор, запрос, словарь и т. Д., Я просто создаю реальную вещь и заполняю тестовыми данными. Это делает тесты более удобочитаемыми и более быстрыми для написания, и, честно говоря, риск отсутствует.

4 голосов
/ 11 февраля 2010

Если вы хотите смоделировать свой репозиторий, вы не будете насмехаться над IQueryable. Вместо этого смоделируйте методы вашего репозитория, чтобы получить фиксированные, известные значения (например, ваш второй пример), которые можно использовать для запуска ваших модульных тестов.

2 голосов
/ 30 июля 2012

Я знаю, что это старый вопрос, но просто хочу добавить мои 2 цента.

У меня была такая же проблема с репозиториями, сгенерированными с помощью SharpLite, который является средой ASP .NET MVC, которую я использую время от времени. Через некоторое время я нашел решение, единственная проблема в том, что он использует Moq, а не Rhino Mocks, но, возможно, вы сможете найти способ его адаптировать. Я сделал сообщение в блоге здесь о том, как это сделать.

Это в основном создание списка, который реализует IQueryable, и использование его в качестве фальшивого фона данных. Надеюсь, я смогу помочь!

0 голосов
/ 12 февраля 2010

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

Я начал с создания интерфейса (IRepository), который включал метод IQueryable. Затем я создал два класса, которые реализуют этот интерфейс. Один класс использует ORM для манипулирования данными (DbEntityRepository), а другой класс использует свойство класса (MemoryRepository). Класс контекста данных имеет конструктор, который требует IRepository. Для этого я мог бы использовать MemoryRepository для тестирования контекста данных и использовать DbEntityRepository для приложения.

Если вам интересно ... вы можете найти код на codeplex: IQToolkitContrib

...