如何在 Scala 中测试对象的私有方法
How to test an object's private methods in Scala
我有一个示例对象:
object Foo {
private def sayFoo = "Foo!"
}
而且我想在没有以下解决方法的情况下测试私有 sayFoo 方法:
1.没有将其定义为包私有
2. 没有将它定义为受保护的,而不是在测试中继承它 class
我看到了一种可能的解决方案,即扩展 privateMethodTester 但它没有
似乎仅适用于 classes.
对象
现在,我知道有些人(如果不是很多)说您不应该测试私有方法,而应该只测试 public 个 (api)。尽管如此,我还是很想测试一下。
感谢进阶
无法通过任何标准方法进行测试。
但是,如果您需要 "cover" 该部分代码,请测试在其实现中使用该私有方法的方法。它是间接的,当然,但它确实有效地测试了代码。
例如,在您的 class 中,您可以使用另一种方法:
def dontSayBar = {
sayFoo()
println("Other processing...")
}
如果测试,这将 "cover" 私有方法中的代码。
P.S。一个好的经验法则是,如果您看到 coverage 运行 中没有出现的代码,那么您可能实际上并不需要该代码。
正如其他人所说,没有办法直接测试私有方法,尤其是对象。
但是你可以通过使用反射来绕过限制。
我不确定是否有更简洁的方法可以使用 Scala 反射来做同样的事情 API,但是下面使用 Java 的反射的代码确实有效:
val m = Foo.getClass.getDeclaredMethod("sayFoo")
val inst = Foo.getClass.getField("MODULE$").get()
m.setAccessible(true)
m.invoke(inst)
首先您需要获得对 sayFoo
方法的引用。接下来,您需要获取对保存在 MODULE$
静态字段中的 Foo 对象的单例实例的引用。
获得两个引用后,您只需要告诉 JVM 从方法中删除访问限制,使其可访问。
这显然是一个丑陋的 hack,但如果谨慎使用并且仅用于测试目的可能会有用。
可能有人已经这样做了:一个注释宏 @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
。
我有一个示例对象:
object Foo {
private def sayFoo = "Foo!"
}
而且我想在没有以下解决方法的情况下测试私有 sayFoo 方法: 1.没有将其定义为包私有 2. 没有将它定义为受保护的,而不是在测试中继承它 class
我看到了一种可能的解决方案,即扩展 privateMethodTester 但它没有 似乎仅适用于 classes.
对象现在,我知道有些人(如果不是很多)说您不应该测试私有方法,而应该只测试 public 个 (api)。尽管如此,我还是很想测试一下。
感谢进阶
无法通过任何标准方法进行测试。
但是,如果您需要 "cover" 该部分代码,请测试在其实现中使用该私有方法的方法。它是间接的,当然,但它确实有效地测试了代码。
例如,在您的 class 中,您可以使用另一种方法:
def dontSayBar = {
sayFoo()
println("Other processing...")
}
如果测试,这将 "cover" 私有方法中的代码。
P.S。一个好的经验法则是,如果您看到 coverage 运行 中没有出现的代码,那么您可能实际上并不需要该代码。
正如其他人所说,没有办法直接测试私有方法,尤其是对象。 但是你可以通过使用反射来绕过限制。
我不确定是否有更简洁的方法可以使用 Scala 反射来做同样的事情 API,但是下面使用 Java 的反射的代码确实有效:
val m = Foo.getClass.getDeclaredMethod("sayFoo")
val inst = Foo.getClass.getField("MODULE$").get()
m.setAccessible(true)
m.invoke(inst)
首先您需要获得对 sayFoo
方法的引用。接下来,您需要获取对保存在 MODULE$
静态字段中的 Foo 对象的单例实例的引用。
获得两个引用后,您只需要告诉 JVM 从方法中删除访问限制,使其可访问。
这显然是一个丑陋的 hack,但如果谨慎使用并且仅用于测试目的可能会有用。
可能有人已经这样做了:一个注释宏 @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
。