1
56
理想情况下,您根本不需要对私有方法进行单元测试。类的所有使用者都应该关心的是公共接口,所以这是您应该测试的。如果一个私有方法有一个bug,它应该被一个在类上调用某个公共方法的单元测试捕获,该方法最终会调用bugy私有方法。如果一个bug成功地溜了过去,这表明您的测试用例没有完全反映您希望类实现的契约。这个问题的解决方案几乎可以肯定是用更仔细的方式测试公共方法,而不是让您的测试用例深入到类的实现细节中。 同样,这是理想情况。在现实世界中,事情可能并不总是那么清楚,让一个单元测试类成为它测试的类的朋友可能是可以接受的,甚至是可取的。不过,这可能不是你一直想做的事情。如果它看起来经常出现,那么这可能表明您的类太大和/或执行了太多的任务。如果是这样,通过将复杂的私有方法集合重构为单独的类来进一步细分它们,应该有助于消除单元测试了解实现细节的需要。 |
2
12
您应该考虑到要测试的样式和方法不同: Black box testing 只测试公共接口(将类视为黑盒)。如果您有一个抽象基类,甚至可以对所有实现使用相同的测试。 如果你使用 White box testing 您甚至可以查看实现的细节。不仅要知道类具有哪些私有方法,还要包括哪些条件语句(例如,如果您希望增加条件覆盖率,因为您知道条件很难编码)。在白盒测试中,类/实现与测试之间肯定存在“高耦合”,这是必要的,因为您希望测试实现而不是接口。 正如bcat指出的那样,使用组合和更多但更小的类,而不是许多私有方法,通常会有所帮助。这简化了白盒测试,因为您可以更容易地指定测试用例以获得良好的测试覆盖率。 |
3
9
我觉得BCAT给出了一个很好的答案,但我想详细说明他提到的例外情况。
我在一家拥有大量遗留代码库的公司工作,这家公司有两个问题,这两个问题都有助于让朋友的单元测试变得可取。
在某些情况下,模拟有助于缓解后一个问题,但这通常只会导致不成功的复杂设计(类继承,否则不需要),而人们可以非常简单地按照以下方式重构代码:
现在我们有了这样的情况:函数的核心部分需要重构,所以我们需要一个单元测试。它不应该公开曝光。现在,有一个奇妙的技术,他称之为模拟,可以在这种情况下使用,但事实是,在这种情况下,模拟是多余的。它将要求我增加复杂的设计与一个不必要的继承权。 一个更务实的方法是这样做:
后者为我提供了单元测试所需的所有好处,包括为我提供了宝贵的安全网,以捕获我在肉中重构代码时产生的错误。为了对它进行单元测试,我必须和一个单元测试类交朋友,但是我强烈地认为这比一个无用的代码继承性要好得多,只是为了让我使用一个模拟。 我认为这应该成为一个习语,我认为这是一个合适的、实用的解决方案,可以提高单元测试的投资回报率。 |
4
5
正如bcat建议的那样,您需要尽可能地使用公共接口本身来查找错误。但是,如果您想做一些事情,比如打印私有变量、与预期结果比较等(有助于开发人员轻松调试问题),那么您可以让UnitTest类成为待测试类的朋友。但您可能需要在下面这样的宏下添加它。
仅当需要单元测试时才启用标记单元测试。 对于其他版本,您需要禁用此标志。 |
5
4
在很多情况下,我认为使用朋友的单元测试类没有任何问题。是的,将一个大类分解成小类有时是更好的方法。我认为人们对于使用friend关键字进行类似的事情有点过于仓促,以至于不能拒绝使用friend关键字-这可能不是理想的面向对象的设计,但是如果这是我真正需要的,我可以牺牲一点理想主义来获得更好的测试覆盖率。 |
6
1
通常,您只测试公共接口,以便可以自由地重新设计和重构实现。为私有成员添加测试用例定义了对类实现的要求和限制。 |
7
0
使要测试的函数受保护。 现在在单元测试文件中,创建一个派生类。 创建在受测试保护的函数下调用类的公共包装函数。 |
overexchange · 客户端锁定是否违反了同步策略的封装? 7 年前 |
mangochaser · java——具有多态性和封装的几何形状 7 年前 |
LBaelish · 安全/正确使用指针[关闭] 8 年前 |
Petr Marek · Javascript类封装行为 8 年前 |