【问题标题】:Remocking a mock function移除一个模拟函数
【发布时间】:2020-09-05 01:51:06
【问题描述】:

说我有特质:

trait A {
    def a(): Boolean
}

还有模拟+测试用例:

trait Fixture {
    val mockA = mock[A]
    (mockA _).returns(true)
}

"mock must return true" in new Fixture {
    mockA() must equal(true)
}

现在,我想将同一测试套件中单个测试的值重新模拟为 false

trait ChildFixture extends Fixture {
    (mockA _).returns(false) // this obviously doesn't work
}
"mock must return false" in new ChildFixture {
    mockA() must equal(false)
}

这是一个非常简化的示例,我有一个复杂的模拟装置依赖链。显而易见的答案是将mockA 的模拟代码提取到另一个夹具中,然后混合到应该为真的那些中,然后为应该为假的特定测试制作一个新夹具。唯一的问题是,鉴于我的测试代码,这是一个繁重的过程。也可以用匿名类和var手动mock返回,但是这样看起来不太优雅,失去了Scala mock调用验证的功能。

是否可以为单个测试重新创建已模拟的对象?

【问题讨论】:

  • 您的灯具是如何工作的?为什么不能选择 override val 之类的东西?
  • @MateuszKubuszok 用夹具设置更新了问题。我没有想到override val,但不幸的是它不起作用。它会在父夹具的模拟设置代码中导致空指针异常。

标签: scala scalatest scalamock


【解决方案1】:

如果你有一个“复杂依赖”的模拟,那么我建议这些模拟不是vals,而是你可以安全覆盖的defs,因为你可以手动调用将结果分配给val在潜在的重写之后。此外,对此类模拟的所有更改都可以在代码块中进行:

trait A {
  def a(): Boolean
}

trait B {
  def b(): B
}

trait Fixture {
  def createMockA(): A = {
    val mocked = mock[A]
    (mocked.a _) returns true
    mocked
  }

  def createMockB(): B = {
    val mocked = mock[B]
    (mocked.b _) returns createMockA
    mocked
  }
}

trait FixtureChild extends Fixture {
  override def createMockA(): A = {
    val mocked = mock[A]
    (mocked.a _) returns false
    mocked
  }
}

"value must be overriden" in new FixtureChild {
  val b = createMockB()
  b.b().a() must beFalse
}

但是,如果您有一个“模拟装置的复杂依赖链”,我会将其视为代码需要重构的危险信号。

【讨论】:

    猜你喜欢
    • 2018-09-04
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2017-02-04
    • 1970-01-01
    • 2015-10-09
    相关资源
    最近更新 更多