Как я могу издеваться или тестировать мою отложенную оценку / функциональность выполнения? - PullRequest
6 голосов
/ 18 мая 2010

У меня есть то, что можно увидеть как причудливый гибрид IQueryable<T> и IList<T> наборов доменных объектов, попавших в мой стек приложений. Я стараюсь поддерживать как можно больше «поздних запросов» или «ленивых загрузок». Я делаю это двумя способами:

  1. Используя слой данных LinqToSql и передавая IQueryable<T> s через хранилища и на уровень моего приложения.
  2. Затем после того, как мой уровень приложения прошел IList<T> s, но там, где определенные элементы в графе объект / агрегат 'связаны' с делегатами , чтобы отложить их загрузку. Иногда даже содержимое делегата опирается на IQueryable<T> источники и DataContext вводится.

Пока это работает для меня.

Что невероятно сложно доказать, что этот дизайн действительно работает. То есть. Если я где-то побеждаю «ленивую» часть, и моя оценка / выполнение происходит рано, то все это пустая трата времени. Я хотел бы быть в состоянии TDD это как-то.

Я не знаю много о делегатах или безопасности потоков, поскольку это относится к делегатам, работающим с одним и тем же источником. Я хотел бы иметь возможность смоделировать DataContext и как-то отследить оба метода отсрочки (SQL IQueryable<T> и делегатов) загрузки, чтобы я мог иметь тесты, которые доказывают, что обе функции работают на разных уровнях / слои приложения / стека.

Поскольку крайне важно, чтобы отсрочка работала для того, чтобы дизайн имел какое-либо значение, я бы хотел, чтобы тесты проваливались, когда я нарушал дизайн на заданном уровне (отдельно от оперативной реализации). Это возможно?

Ответы [ 2 ]

4 голосов
/ 24 мая 2010

В morelinq у нас есть так называемая «последовательность прерывания», чтобы проверить это. По сути, это перечислитель, который будет генерировать исключение при каждом его перечислении.

Это может быть так же просто, как:

internal sealed class BreakingSequence<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
        throw new InvalidOperationException();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Тест на это выглядит так:

   [Test]
    public void XyzIsLazy()
    {
        var source = BreakingSequence<EntityClass>().AsQueryable();

        // inject it as your query source wherever appropriate
        var query = source.Where(x=> true);
        // does not throw, where does not enumerate the sequence
    }
2 голосов
/ 28 мая 2010

Я собираюсь ответить в том же духе, что ответил Иоганн Рудольф. Похоже, что вы думаете правильно, хотите пройти тест на что-то важное, что было бы трудно отследить в случае неудачи.

Я бы определенно предложил использовать макет для этой цели. Йоханнес предложил объект, который выдает исключение при перечислении. Поскольку ваш объект является шаблонным, я считаю, что вы должны иметь возможность использовать любой объект, который хотите. Может быть очень полезен фальшивый фреймворк, такой как Rhino.Mocks (бесплатно) или TypeMock Isolator (дорого). Я настоятельно рекомендую изучить фальшивые рамки, если вы еще этого не сделали.

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

...