Я имею то, что могло рассматриваться как причудливый гибрид IQueryable
и IList
наборы объектов области отказались от моего стека приложений. Я пытаюсь поддержать такие же большие 'последние запросы' или 'ленивую загрузку' как возможные. Я делаю это двумя способами:
IQueryable
s через репозиториями и к моему слою приложения.IList
s, но где определенные элементы в объектном/совокупном графике 'объединяются в цепочку' с делегатами, чтобы задержать их загрузку. Иногда даже содержание делегата полагается IQueryable
источники и DataContext
введены.Это работает на меня до сих пор.
То, что является ослепляюще трудным, доказывает, что этот дизайн на самом деле работает. Т.е. Если я побеждаю 'ленивую' часть где-нибудь, и моя оценка/выполнение происходит рано затем, все это - пустая трата времени. Я хотел бы смочь к TDD это так или иначе.
Я не знаю много о делегатах или потокобезопасности, поскольку она относится к делегатам, действующим на тот же источник. Я хотел бы смочь дразнить DataContext
и так или иначе проследите оба метода задержки (IQueryable
SQL и делегаты) загрузка так, чтобы у меня могли быть тесты, которые доказывают, что обе функции работают на различных уровнях/слоях приложения/стека.
Поскольку крайне важно, чтобы задержка работала на дизайн для имения любую ценность, я хотел бы видеть тестовый сбой, когда я повреждаю дизайн на данном уровне (отдельный от живой реализации). Действительно ли это возможно?
В 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
}
Я отвечу в том же ключе, что и Йоханнес Рудольф. Похоже, что вы думаете правильно, желая иметь тест для чего-то важного, что будет трудно отследить в случае неудачи.
Я бы определенно предложил использовать для этой цели макет. Йоханнес предложил объект, который выбрасывает исключение, когда его перечисляют. Поскольку ваш объект является типовым, я считаю, что вы можете использовать любой объект, какой захотите. Очень полезным может оказаться использование mocking framework, например, Rhino.Mocks (бесплатный) или TypeMock Isolator (дорогой). Я настоятельно рекомендую изучить фреймворки mocking, если вы еще этого не сделали.
Имея в руках макет, вы можете оценить, что операции должны выполняться в определенном порядке при запуске определенного тестового кода. Вы можете запрограммировать свой макет на запись того, какие операции происходят, а затем проверить запись в конце теста.