我已经阅读了这篇关于如何测试私有方法的文章。我通常不测试它们,因为我总是认为只测试将从对象外部调用的公共方法更快。你测试私有方法吗?我应该一直测试它们吗?


当前回答

其中一个要点是

如果我们测试以确保逻辑的正确性,并且私有方法携带逻辑,那么我们应该测试它。不是吗?我们为什么要跳过这个呢?

基于方法的可见性编写测试是完全无关的想法。

相反

另一方面,在原始类之外调用私有方法是一个主要问题。在一些模拟工具中,模拟私有方法也有局限性。(例:5)

虽然有一些工具如Power Mock支持这一点,但这是一个危险的操作。原因是它需要破解JVM来实现这一点。

一种可以解决的方法是(如果您想为私有方法编写测试用例)

将这些私有方法声明为受保护的。但在某些情况下可能不方便。

其他回答

绝对是的。这就是单元测试的要点,你测试单元。私有方法是一个单元。没有测试私有方法,TDD(测试驱动开发)是不可能的,

我不对私有方法进行单元测试。私有方法是应该对类的用户隐藏的实现细节。测试私有方法会破坏封装。

如果我发现私有方法非常庞大、复杂或重要到需要自己的测试,我就把它放在另一个类中,并在那里将它设为公共(方法对象)。然后,我可以轻松地测试以前是私有但现在是公共的方法,该方法现在存在于它自己的类中。

“我应该测试私有方法吗?”的答案是“有时.......”。通常情况下,您应该针对类的接口进行测试。

其中一个原因是您不需要对一个特性进行双重覆盖。 另一个原因是,如果您更改了私有方法,则必须为它们更新每个测试,即使对象的接口根本没有更改。

这里有一个例子:

class Thing
  def some_string
    one + two
  end

  private 

  def one
    'aaaa'
  end

  def two
    'bbbb'
  end

end


class RefactoredThing
def some_string
    one + one_a + two + two_b
  end

  private 

  def one
    'aa'
  end

  def one_a
    'aa'
  end

  def two
    'bb'
  end

  def two_b
    'bb'
  end
end

在RefactoredThing中,你现在有5个测试,其中2个你必须为重构而更新,但你的对象的功能实际上没有改变。所以让我们假设事情比这更复杂,你有一些方法来定义输出的顺序,比如:

def some_string_positioner
  if some case
  elsif other case
  elsif other case
  elsif other case
  else one more case
  end
end

这不应该由外部用户来运行,但是您的封装类可能太笨重了,无法一遍又一遍地运行这么多逻辑。在这种情况下,您可能更愿意将其提取到一个单独的类中,为该类提供一个接口并对其进行测试。

最后,假设你的主对象非常重,方法非常小你需要确保输出是正确的。你会想,“我必须测试这个私有方法!”也许你可以通过传入一些繁重的工作作为初始化参数使你的对象更轻?然后你可以放一些更轻的东西进去测试。

我倾向于遵循Dave Thomas和Andy Hunt在他们的书《实用单元测试》中的建议:

一般来说,为了不破坏任何封装 测试(或者就像妈妈常说的,“不要暴露你的私处!”)。大多数 此时,您应该能够通过执行类的 公共方法。如果隐藏了重要的功能 在私人或受保护访问的背后,这可能是一个警告信号 还有一群人在里面挣扎着想出来。

但有时我无法阻止自己测试私有方法,因为它给了我一种安全感,我正在构建一个完全健壮的程序。

正如上面引用的,“如果你不测试你的私有方法,你怎么知道它们不会崩溃?”

这是一个大问题。单元测试的一个重要要点是尽快知道在哪里、何时以及如何发生故障。这样就减少了大量的开发和QA工作。如果所有测试的都是公开的,那么您就没有对类的内部进行诚实的覆盖和描述。

我发现最好的方法之一是将测试引用添加到项目中,并将测试放在与私有方法并行的类中。放入适当的构建逻辑,这样测试就不会构建到最终项目中。

然后,您就有了测试这些方法的所有好处,您可以在几秒钟内而不是几分钟或几小时内发现问题。

总之,单元测试你的私有方法。