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

问题描述 投票:1回答:1

考虑以下示例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”,它是null,因为我没有传递任何东西,因为我想要的是一个存根,在调用特定方法时返回一个特定的值。

有没有办法创建存根而不试图调用对象的构造函数?为什么这适用于旧版本?

scala unit-testing scalatest scalamock
1个回答
1
投票

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

由于mocks是子类,因此将调用超类的构造函数 - 没有例外。你可以使用一些cglib法术来解决这个问题,但这不是我熟悉的事情。

因此,在旧的ScalaMock版本中可能已经可以实现这一功能,但是此功能不会在当前实现的情况下很快恢复。

另一个选择是实际上自己子类化这个东西并模拟子类

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

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

© www.soinside.com 2019 - 2024. All rights reserved.