如何在Scala中测试对象的私有方法

时间:2015-10-27 18:45:44

标签: scala unit-testing object testing private

我有一个示例对象:

object Foo {
  private def sayFoo = "Foo!"
}

我想在没有以下解决方法的情况下测试私有的sayFoo方法: 1.没有将其定义为包私有 2.没有将其定义为受保护,而是在测试类中继承它

我看到了一个可能的解决方案,即扩展privateMethodTester,但它没有 似乎只为类对象工作。

现在,我知道有些人,如果不是很多人,说你不是要测试私人方法,而只是测试公共方法(api)。尽管如此,我仍然想测试它们。

高级

3 个答案:

答案 0 :(得分:2)

无法通过任何标准手段进行测试。

但是,如果您需要“覆盖”该部分代码,请测试在其实现中使用该私有方法的方法。它是间接的,被授予,但它确实有效地测试了代码。

例如,在您的课程中,您可以使用另一种方法:

def dontSayBar = {
    sayFoo()
    println("Other processing...")
}

如果进行测试,这将“覆盖”私有方法中的代码。

P.S。一个好的经验法则是,如果您看到代码未在coverage运行中显示,那么您可能实际上并不需要该代码。

答案 1 :(得分:2)

正如其他人所说,没有办法直接测试私有方法,特别是对象。 但是,您可以通过使用反射作弊来绕过限制。

我不确定使用Scala反射API是否有更简洁的方法来执行相同操作,但是以下使用Java反射的代码确实有效:

val m = Foo.getClass.getDeclaredMethod("sayFoo")
val inst = Foo.getClass.getField("MODULE$").get()
m.setAccessible(true)
m.invoke(inst)

首先,您需要获得sayFoo方法的引用。接下来,您需要获取对Foo对象的单例实例的引用,该实例保存在MODULE$静态字段中。

一旦你有两个引用,你只需告诉JVM从方法中删除访问限制,使其可访问。

这显然是一个丑陋的黑客,但如果谨慎使用并且仅用于测试目的可能是有用的。

答案 2 :(得分:0)

可能有人已经这样做了:注释宏@Testable如何通过暴露私有成员的方法发出对象,但仅在编译测试时(以及其他对象)。

scala> object X { private def f = 42 ; def g = 2 * f }
defined object X

scala> X.g
res1: Int = 84

scala> object X { private def f = 42 ; def g = 2 * f ; def testable = new { def f = X.this.f } }
defined object X

scala> X.testable.f
warning: there was one feature warning; re-run with -feature for details
res2: Int = 42

scala> object X { private def f = 42 ; def g = 2 * f ; def testable = new Dynamic { def selectDynamic(name: String) = X.this.f } }
defined object X

scala> X.testable.f
warning: there was one feature warning; re-run with -feature for details
res4: Int = 42

或者,它可以发出不同的object TestableX