如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?

仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。


当前回答

如果你担心没有像很多帖子所建议的那样测试私有方法,那么考虑一下代码覆盖工具将准确地确定你的代码被测试了多少以及泄漏的地方,所以这样做是可以接受的。

将问题作者引向“变通方法”的答案对社区造成了巨大的伤害。测试是所有工程学科的主要组成部分。你不会想买一辆没有经过适当测试的汽车,而且测试的方式很有意义,那么为什么有人会想购买或使用测试不好的软件呢?人们这样做的原因可能是因为测试不好的软件的影响是事后才感受到的,我们通常不会把它们与身体伤害联系起来。

这是一种非常危险的观念,很难改变,但我们有责任提供安全的产品,而不管管理层如何欺负我们。想想Equifax黑客。。。

我们必须努力营造一个鼓励良好软件工程实践的环境。这并不意味着排斥我们中那些不认真对待自己手艺的弱者/懒惰者,而是创造一种责任感和自我反思的现状,鼓励每个人在精神和技能上追求成长。

我仍在学习,可能自己也有错误的看法/观点,但我坚信,我们需要对良好做法负责,避免不负责任的黑客或解决问题的方法。

其他回答

下面是我测试私有字段的通用函数:

protected <F> F getPrivateField(String fieldName, Object obj)
    throws NoSuchFieldException, IllegalAccessException {
    Field field =
        obj.getClass().getDeclaredField(fieldName);

    field.setAccessible(true);
    return (F)field.get(obj);
}

JUnit.org常见问题解答页面的答案:

但如果你必须。。。如果您使用的是JDK1.3或更高版本,则可以使用反射来颠覆访问控制机制。有关如何使用它的详细信息,请阅读本文。如果您使用的是JDK1.6或更高版本,并且使用@测试时,可以使用Dp4j在测试方法中注入反射。对于有关如何使用它的详细信息,请参阅此测试脚本。

P.S.我是Dp4j的主要贡献者。问我你是否需要帮助。:)

首先,我要抛出一个问题:为什么你的私人成员需要隔离测试?它们是否如此复杂,提供了如此复杂的行为,以至于需要在公共表面之外进行测试?这是单元测试,而不是“代码行”测试。别为小事操心。

如果它们是那么大,足够大,以至于这些私有成员都是一个复杂度很大的“单元”,那么考虑将这些私有成员从这个类中重构出来。

如果重构不合适或不可行,在进行单元测试时,是否可以使用策略模式来替换对这些私有成员函数/成员类的访问?在单元测试中,该策略将提供额外的验证,但在发布版本中,它将是简单的传递。

测试私有方法的最佳方法是通过另一个公共方法。如果无法做到这一点,则以下条件之一为真:

私有方法是死代码您正在测试的类附近有设计气味您尝试测试的方法不应是私有的

在C++中:在包含包含要测试的私有函数的类头之前。

使用此代码:

#define private public
#define protected public