【问题标题】:How do you create a ScalaMock stub that doesn't call the constructor of the underlying object?如何创建一个不调用底层对象构造函数的 ScalaMock 存根?
【发布时间】:2018-12-21 01:09:48
【问题描述】:

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

有没有办法在不尝试调用对象的构造函数的情况下创建存根?为什么这在旧版本中有效?

【问题讨论】:

    标签: scala unit-testing scalatest scalamock


    【解决方案1】:

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

    由于模拟是子类,超类的构造函数将被调用 - 没有例外。 你也许可以使用一些 cglib 巫术来解决这个问题,但这不是我所熟悉的。

    因此,这在旧 ScalaMock 版本中可能是可能的,但当前实现不会很快恢复此功能。

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

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

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

    【讨论】:

    • 很高兴知道,谢谢。我没有意识到 ScalaMock 只是生成了子类。我想这会教我处理空构造函数输入。
    猜你喜欢
    • 2012-07-06
    • 2013-09-24
    • 2018-07-06
    • 2019-07-25
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多