4

假设我有一个带有将 System.Linq.Expressions.Expression 作为参数的方法的类,那么在单元测试中有多少价值?

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

单元测试或模拟这些方法对我来说是一次令人兴奋的经历,我现在不得不怀疑这一切是否不值得。

我将如何使用一些任意表达式对这种方法进行单元测试,例如

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

2 回答 2

6

对此进行单元测试有点人为,因为每个 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 查询限制在数据层,则可以消除风险,现在您正在测试(/模拟)一个纯粹的、可预测的接口。

在这里讨论更多

于 2010-04-22T03:54:02.493 回答
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 以便内部 somecollection 包含一些已知对象 - 例如 Add(dog); 添加(猫);等等
  2. 动作:使用条件调用 Find 方法
  3. 断言:Assert.That( results.Is.EquivalentTo(expected_results)

您可以尝试几个查询表达式来确保 Find 方法将其用作 Where 子句。那应该这样做。

于 2010-04-22T02:45:04.293 回答