11

添加返回对象内部状态以进行单元测试的函数是否比让测试类成为朋友更好?- 特别是当除了单元测试的情况之外没有使用功能时。

4

6 回答 6

12

单元测试应该 95% 的时间只测试一个类的公开暴露的表面。如果您在幕后测试某些东西,那就是测试实现细节,这本质上是脆弱的,因为您应该能够轻松更改实现并且仍然让测试工作。它不仅脆弱,而且您还可能会尝试测试在计划的使用场景中实际上不可能的东西,这是浪费时间。

如果您要添加的访问器的目的只是为了测试该函数是否具有预期的效果,那么您的类设计可能会违反另一个原则,即类似状态机的类应该始终明确其处于什么状态,如果这会影响人们与班级互动时发生的事情。在这种情况下,提供那些只读访问器是正确的。如果它不影响类的行为,请参考我之前关于实现细节的部分。

正如你所说的那样,由于其自​​身的原因,用未使用的东西弄乱一个类的公共表面也是不可取的。

如果我必须在您的情况下在访问者和交友之间进行选择,我会选择交友,因为拥有您的测试并且可以在紧要关头更改它。你可能不拥有那些找到使用额外访问器的方法的小丑的代码,然后你就会被卡住。

于 2009-07-19T05:44:32.110 回答
9

我不同意接受的答案,而是建议使用朋友课程。

您正在测试的部分状态可能特定于您的类的实现;您正在测试其他代码通常不知道或不关心且不应依赖的细节。公共访问器函数使这些实现细节成为类接口的一部分。如果您正在测试的内部状态不是预期接口的一部分,则它不应该通过公共函数可见。从纯粹主义者的角度来看,您被困在两个错误答案之间,因为朋友类在技术上也是公共接口的一部分。在我看来,问题变成了,哪个选项不太可能导致未来的编码选择不佳?使用一组依赖于实现的公共访问器函数将无意中鼓励类的依赖于实现的概念模型,导致类的依赖于实现的使用。适当命名和记录的单个朋友类不太可能被滥用。

虽然总的来说,我强烈同意更喜欢访问器函数而不是直接访问成员变量的建议,但我不同意这种最佳实践适用于依赖于实现的内部状态的单元测试。一个合理的中间立场是对您的单元测试将关心的那些状态使用私有访问器函数,并有足够的纪律在您的单元测试中使用访问器函数。只是我的观点。

于 2009-07-19T05:48:43.757 回答
3

使用友元类进行单元测试是完全合法的,并且允许您维护封装。您不应该仅仅为了使类更可测试而修改您的类公共接口。这样想吧。如果您购买了第三方 FTP 库并尝试使用它,并且它的公共界面中充斥着一堆您甚至不需要仅仅因为单元测试而知道的方法!即使修改受保护的接口来补偿单元测试也是不好的。如果我从某个类继承,我不想担心哪些方法对我有用,哪些方法只是因为单元测试才存在!!!使用friends 类进行单元测试可以帮助您维护一个简单、更易于使用的类接口;它有助于保持封装和抽象!!!

我听说过使用友元类进行单元测试不好的论点,因为被测类不应该与其测试类“紧密耦合”,并且它不应该“知道”任何关于它的测试类的信息。我不买这个。这是添加到类顶部的一行:

朋友班 MyClassTest;

现在你可以用任何你想要的方式测试你的课程了!

现在我同意你不应该使用朋友类,除非有必要。如果您可以测试需要测试的内容而无需成为朋友,那么一定要这样做。但是,如果生活变得困难并且使用朋友课程让生活再次变得轻松,那就使用它吧!

于 2010-11-13T06:11:00.470 回答
1

我建议使用访问器而不是允许通过公共成员或朋友类进行访问。

我不认为使用朋友班实际上会给你带来任何好处,而且它有可能让你的生活变得更糟。如果您的代码将长期存在,那么它很有可能会以您未预料到的方式使用。访问功能现在可能只用于测试,但谁知道将来会发生什么?使用访问器而不是提供对变量的直接访问为您提供了更多的灵活性,并且成本非常低。

另一个论点是使用访问器而不是公共成员是一个好习惯。养成良好的习惯是程序员的一项重要技能。

于 2009-07-19T04:41:26.730 回答
0

如何使内部状态“受保护”?然后使用派生类进行单元测试。

于 2009-07-19T08:00:10.743 回答
0

我认为需要在通过向其用户提供访问器(如果这样做是有意义的)和提高可测试性的情况下对类进行面向未来的区分。我也不是仅仅为了测试而与类交朋友的忠实粉丝,因为这在我不想拥有它的地方引入了紧密耦合。

如果访问器的唯一用途是为测试用例提供一种检查类内部状态的方法,那么公开它们通常是没有意义的。它还可以限制您以后可能希望更改但发现您无法更改的实现细节,因为其他人正在使用所述访问器。

我首选的解决方案是提供受保护的访问器函数,以便向类的用户清楚地传达这些不是公共接口的一部分。然后,您的测试将创建原始的最小派生类,其中包含父函数的调用存根,但也使访问器公开,以便您可以在测试用例中使用它们。

于 2009-07-19T08:06:37.503 回答