单元测试辅助方法?

时间:2009-12-07 17:02:02

标签: java unit-testing junit jmock helpermethods

我有以前有大量方法的类,所以我把这个方法的工作细分为'helper'方法。

这些帮助器方法被声明为private以强制封装 - 但是我想对大型公共方法进行单元测试。对辅助方法进行单元测试也是好的,就好像其中一个方法失败了,调用它的公共方法也会失败,这样我们就可以找出它失败的原因了吗?

另外,为了使用模拟对象测试这些,我需要将其可见性从私有更改为受保护,这是否可取?

9 个答案:

答案 0 :(得分:14)

这闻起来你有错误的问题。你所描述的类似于创建一个子单元测试,这让我相信你的单元测试毕竟是在测试一个单元。

这不是对你要做的事情的批评:从“我们今天所处的地方”到“其他可以改善的地方”是一个成功的举措。然而,建议你退后一步来评估你的位置 - 了解你当前的情况与柏拉图式的一些理想有何不同可以帮助展示新的可能性。

这里有很多关于确定你的助手方法的建议。另一种可能性是检查实现以确定当前实现中是否存在潜伏类。创建一个新类和一套测试来运用它总是可以接受的。

请注意,这种方法可以使您免于重构:您可以在不更改测试套件的情况下更改实现(因为即使辅助对象不再是生产实现的一部分,辅助对象的单元测试也会继续通过),并且你得到了一个干净的实现包装和它的测试(用例:你决定bozo-sort是错误的实现,不应该再使用。如果bozo-sort实现被隔离,那么你只需删除它,它的测试。但是当所有其他测试结合了bozo-sort实现的测试时,会有更多的思考。)

查看为什么要对代码进行单元测试也可能有所帮助。如果其中一个原因是“使重构安全”,那么您不希望编写将您锁定到实现中的测试。

答案 1 :(得分:12)

一种方法是省略private并将测试放在同一个包中。然后测试可以调用内部方法,但没有其他人(在包外面)可以。

此外,内部方法失败应产生错误消息,以便于解决问题。当您将代码投入生产时,您将看到比测试更少的内容,并且您将面临很大的压力来快速解决问题。因此,一小时后在这里花一分钟就可以让你的老板坐在你的脖子上。

答案 2 :(得分:8)

如果你的课真的那么大,那么听起来你应该打破帮助对象,而不仅仅是助手方法(虽然提取方法通常是一步之遥方式)。完成后,您的旧类变得更简单,更容易测试(可能使用模拟,也许不是),您可以直接在新的支持类上测试方法。

我的偏好是通过对象的公共API进行测试。如果那太难了,那么就暗示该对象应该被打破。

答案 3 :(得分:3)

如果您想测试 Helper 方法,可以将其从私有方式更改,但您可能会考虑这一点。

您不应该对您的实施的私有细节进行单元测试,主要是因为它可能会因重构和“中断”您的测试而发生变化。

答案 4 :(得分:3)

我对这里的一些答案感到非常震惊。

本质上有些人说“不要测试私有代码,因为这违反了TDD范式”

测试该死的代码。做任何你需要的东西,以确保它完全按照它应该的方式工作。

就个人而言,我会使方法受到保护或默认,编写测试,运行测试,并在成功时,恢复为私有。在这一点上,我会评论出相关的测试,并在它们上面留下一个指令块:

/ **对此抱歉,但我继承了一个烂摊子...... *如果您需要测试这些方法,请在源代码中公开它们并取消注释以下*行 * /

但绝对不要让严格遵守开发方法会妨碍改进代码。

答案 5 :(得分:1)

这是其中一个我会说继续违反规则的案例。

如果你是从头开始设计这个类,你绝对不希望自己的辅助方法进行单元测试,但是......因为你正在重构一个现有的类,所以弯曲规则是可以接受的确定你没有破坏任何东西。

让它们受到保护会让你自己测试帮助程序,以确保它们仍然具有你期望的行为,因为你将逻辑从大毛球方法中拉出来,并允许你将它们存根并返回固定的响应这样你就可以确保你重构的大方法对于辅助方法的某些结果的预期行为是正常的。

但那时你还没有完成。拆分方法并不是真正解决问题的根源。既然你已经分解了这个方法,并且有一组(略微非正统的)测试可以准确地显示所有逻辑的功能,那么你就可以重新检查整个类并试图找出方法的原因。一开始这么大。最有可能的是,您的整个班级也需要分解成具有离散职责的较小单位,这样可以更容易地进行测试而不会违反任何规则。

答案 6 :(得分:0)

你基本上有两个选择:

  1. 将辅助方法的范围从private增加到default。然后,您可以测试这些方法(假设测试类与测试主题位于同一个包中)。这提高了类的可测试性,但是你牺牲了一些封装

  2. 保持一切顺利。这将阻止您编写非常细粒度的测试,但不要求您牺牲任何封装。

  3. 就个人而言,我会选择(2),因为你不应该真的需要测试私有方法。该类应该通过它的公共接口进行测试(它反过来将调用私有方法。测试私有方法可能导致脆弱的测试,即当只有类的内部行为发生变化时测试失败。

    还有第三个选项(我不愿意提及):使用反射(或其他一些伏都教)来调用测试类中的私有方法。这具有(1)的缺点以及反射代码固有的缺点(例如绕过类型检查并且难以阅读)

答案 7 :(得分:0)

正如Don和Dror所说,将这些方法设为公开,这样你就可以为它们创建单元测试,从而打破封装。然后,您将自己绑定到特定的实现。通过公开它们,你向全世界宣告这些方法是已发布接口的一部分,因此它们的规范被锁定。

就个人而言,我会寻求更实用的解决方案:将它们保密,不要编写单元测试。如果你遇到一个公共方法失败的情况,你不知道为什么但你认为它可能是你的一个私有方法中的问题,那么暂时将它们公开,编写单元测试,调试,当你完成后,再次将它们设为私有并注释掉单元测试。

答案 8 :(得分:0)

您可以通过编写执行代码部分的单元测试来对这些辅助方法进行单元测试。

您在此课程中定义了一个公共API是有原因的,对吗?测试一下。如果它有效,该课程就可以了。

使用代码覆盖率工具来帮助您了解是否正在测试该类的足够部分,如果不是,请编写更多单元测试来练习公共API并点击那些未被覆盖的角落。