Должны ли методы, содержащие выражения LINQ, быть проверены / смоделированы? - PullRequest
4 голосов
/ 22 апреля 2010

Предполагая, что у меня есть класс с методом, который принимает System.Linq.Expressions.Expression в качестве параметра, какое значение имеет его модульное тестирование?

public void IList<T> Find(Expression expression)
{
    return someCollection.Where(expression).ToList();
}

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

Как бы я протестировал этот метод, используя произвольное выражение, такое как

List<Animal> = myAnimalRepository.Find(x => x.Species == "Cat");

Ответы [ 2 ]

6 голосов
/ 22 апреля 2010

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

List<Animal> = myAnimalRepository.Find(x => CheckSpecies(x, "Cat"));
...
static bool CheckSpecies(Animal animal, string species) {
    return animal.Species == species;
}

Это будет работать с LINQ-to-Objects ... но только с LINQ-to-Objects. Аналогично, использование UDF (или одного из вспомогательных методов SQL) будет работать в LINQ-to-SQL, но не в Entity Framework.

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

Еще лучший подход, IMO, - не выставлять это через интерфейс вашего хранилища. Если вы ограничиваете запросы LINQ уровнем данных, вы устраняете риск, и теперь вы тестируете (/ mocking) чистый, предсказуемый интерфейс.

Я обсуждаю это подробнее здесь .

2 голосов
/ 22 апреля 2010

Почему бы и нет? - Он является частью открытого интерфейса SUT.

Это тоже легко проверить. Я обычно не использую издевательства, если это абсолютно не требуется. Я бы написал тест как

[Test]
public void Find()
{
  var animalRepository = new AnimalRepository();
  animalRepository.Add( dog ); // create a object to species = dog and other relevant attr
  animalRespository.Add( cat ); // etc. etc..

  var results = animalRepository.Find( a => a.Species == "Cat");

  Assert.That( results.Is.EquivalentTo( new List<Animal> { cat } ) );
}
  1. Arrange: настройте SUT так, чтобы внутренняя коллекция содержала несколько известных объектов, например Добавить (собака); Добавить (кошка); и т.д.
  2. Act: вызывать метод Find с условием
  3. Утверждение: Assert.That( results.Is.EquivalentTo(expected_results)

Вы можете попробовать пару выражений запроса, чтобы убедиться, что метод Find использует его в качестве предложения Where. Это должно сделать это.

...