是否应该测试/模拟包含LINQ表达式的方法?

时间:2010-04-22 01:53:19

标签: c# unit-testing mocking linq-expressions

假设我有一个带有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 个答案:

答案 0 :(得分:6)

unit 测试它有点人为,因为每个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中运行,但不适用于实体框架。

我得出结论,只有集成测试对这种情况有用,所以没有;在这里嘲笑不是非常有帮助。它会给你一种温暖的快乐感觉,你已经做了一些有用的事情,但最终它没有测试你在你的应用程序中写的内容是否有效。

更好的方法,IMO,不是通过您的存储库接口公开这样的方法。如果将LINQ查询限制为数据层,则可以消除风险,现在您正在测试(/模拟)纯粹的可预测接口。

我讨论了这个more here

答案 1 :(得分:2)

为什么不呢? - 它是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. 安排:设置SUT,以便内部的一些收集包含一些已知的对象 - 例如加入(狗);加入(猫);等
  2. Act:使用条件
  3. 调用Find方法
  4. 断言:Assert.That( results.Is.EquivalentTo(expected_results)
  5. 您可以尝试使用几个查询表达式来确保Find方法将其用作Where子句。应该这样做。

相关问题