如何创建不调用基础对象的构造函数的ScalaMock存根?

时间:2018-07-12 17:55:00

标签: scala unit-testing scalatest scalamock

考虑以下示例Scala类和单元测试:

class BrokenClass(s: String) {
  private val len = s.length
  def length(): Int = len
}

class BrokenTest extends FlatSpec with Matchers with MockFactory {

  "A BrokenClass" should "stub correctly" in {
    val stubThing = stub[BrokenClass]
    (stubThing.length _) when () returns (10)
    stubThing.length should equal (10)
  }

}

在旧版本的ScalaMock中,此代码将起作用。使用Scala 2.12和ScalaMock 3.6,我得到了NullPointerException,因为即使创建存根,它仍在调用BrokenClass构造函数的“ s.length”行。因此,它试图取消对“ s”的引用,这是空的,因为我没有传递任何东西给它,因为我想要的只是一个存根,当调用特定方法时,该存根会返回特定值。

是否有一种创建存根而不尝试调用对象的构造函数的方法?为什么在旧版本中可以使用此功能?

1 个答案:

答案 0 :(得分:1)

ScalaMock使用宏定义生成子类。 该宏在编译器运行期间被扩展/评估。

由于模拟是子类,因此将调用超类的构造函数-不例外。 您也许可以使用某些cglib魔术来解决此问题,但这不是我所熟悉的。

因此,在较早的ScalaMock版本中可能会发生这种情况,但是此功能不会在当前实现中很快恢复。

另一种选择是实际自己将此子类继承并模拟子类

class NotSoBrokenClass extends BrokenClass("")
...
val nsb = mock[NotSoBrokenClass]
...

在某些情况下可行,但是如果构造函数依赖于非最终方法调用,您也会看到有趣的行为(例如NPE)。