在单元测试中使用反射来进行复杂对象断言是一种不好的做法吗?

9 浏览
0 Comments

在单元测试中使用反射来进行复杂对象断言是一种不好的做法吗?

我正在阅读关于使用反射来测试私有变量的这个主题,但是在我的单元测试中并没有这样的问题,我的代码是完全可测试的。\n唯一的问题是,当对一个复杂对象的每个属性进行断言时,特别是对一个复杂对象列表进行断言时,这是非常耗时的。\n由于它是一个复杂对象,使用普通的Assert.AreEqual不会给我一个正确的结果,除非我为每个对象实现IEquality。\n但即使这样做,这也不会告诉我在断言期间哪个属性/字段的名称、期望值和实际值。\n正确的做法是,我们手动将每个属性值放入一个列表中,并进行单个的CollectionAssertion,但这仍然很耗时,而且在断言发生时只告诉我元素值不相等的索引;它不会告诉我属性名称。这使得调试非常困难(我必须进入调试模式并查看集合中的元素)。\n所以我想知道,如果我编写一个递归的反射方法,在两个复杂对象上进行断言,它将告诉我每个属性名称、期望值和实际值。\n这是一种好的做法还是不好的做法?

0
0 Comments

在正常情况下,您不应该使用反射来进行任何与单元测试相关的操作。这在您提供的链接中的答案中已经提到:

反射真的只应该作为最后的手段

如果您需要检查复杂对象是否相等,请在单元测试中实现这样的相等检查。在单元测试目的下添加额外的代码并没有问题:

public void ComplexObjectsAreEqual()
{
    var first = // ...
    var second = // ...
    AssertComplexObjectsAreEqual(first, second);
}
private void AssertComplexObjectsAreEqual(ComplexObject first,
    ComplexObject second)
{
    Assert.That(first.Property1, Is.EqualTo(second.Property1),
       "Property1 differs: {0} vs {1}", first.Property1, second.Property1); 
    // ...
}

您真的不应该把单元测试看作是其他代码。如果需要编写一些代码使它们更易读、干净、可维护-请编写它们。这和其他地方的代码是一样的。您会在生产代码中使用反射比较对象吗?

0
0 Comments

使用反射来进行复杂对象断言在我看来并不是一个很好的选择。使用反射意味着我们在编译时失去了类型安全性。而且,在使用反射的背后,可能会通过对程序集元数据进行不区分大小写的字符串搜索。这会导致性能下降。考虑到这些方面,我认为将原始类型拆分(正如oleksii建议的)是一个好的方法。

另一种方法是编写独立的测试,使用纯访问器方法来测试不同的属性集。这在某些情况下可能不适用,但在某些情况下是可行的。

例如:如果我有一个Customer类,我可以编写一个测试来检查Address类型的字段;我可以编写另一个测试来检查Order类型的字段,依此类推。

嗯,你能给我一个使用这种断言方法的类型安全性的例子吗?因为基本上方法本身应该检查两个对象是否是相同的类型,因此它们的属性也应该是相同的。当对每个属性进行断言时,需要检查两个属性的值(并且属性类型相同)。

我指的是属性名称或类型名称的更改。我不知道你的程序集的结构。我想,如果使用不同的工厂方法来生成这两个对象,使用反射可能意味着我们要进行更多的检查。

因此,使用反射进行复杂对象断言可能导致性能下降,并且在编译时失去了类型安全性。解决这个问题的方法之一是将原始类型拆分为较小的部分进行测试,另一种方法是使用纯访问器方法来测试不同的属性集。这样可以避免使用反射,提高性能和类型安全性。

0
0 Comments

问题是:在单元测试中使用反射来进行复杂对象断言是否是一种不好的实践?

出现这个问题的原因是:

- 使用反射可能会导致性能和类型安全等方面的问题。

- 当你在属性中使用的类型不是你自己拥有的类型时,强制实现相等性比较可能会遇到问题。

- 编写许多细小的比较器类与手动编写断言一样耗时。

解决方法是:

- 可以编写一个扩展方法来实现所描述的功能。

- 方法会比较两个相同类型的对象(或实现了相同接口的对象)。

- 使用反射来找到所有公共属性。

- 对于值类型的属性,直接使用Assert.AreEqual进行比较。

- 对于引用类型的属性,进行递归调用。

- 测试不关心属性名称,因此重构时不会产生问题。

- 使用这种方法进行测试时,可以自动发现新属性并忽略已删除的属性。

- 在过去的使用中没有遇到性能问题,但并没有测试过非常复杂的对象。

- 在的观点中,在单元测试中谨慎使用反射是可以接受的。

0