重新模拟模拟功能

时间:2020-05-19 05:00:36

标签: scala scalatest scalamock

说我有特征:

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的模拟代码提取到另一个夹具中,然后混合到应该为true的夹具中,然后为应该为false的特定测试创建一个新夹具。唯一的问题是,鉴于我的测试代码,这是一个繁重的过程。还可以使用匿名类和var手动模拟返回值,但这看起来并不优雅,并且会失去Scala模拟调用验证的功能。

是否可以将已模拟的对象重新用于单个测试?

1 个答案:

答案 0 :(得分:1)

如果您对模拟具有“复杂的依赖性”,那么我建议您可以放心地覆盖val这些模拟而不是def,因为您可以将结果分配给可能重写后,手动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
}

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