模拟案例 class 进行测试

Mocking a case class for testing

我有案例class

case class InputCriteria(a: Int) {
   val b: Int = config.getInt("some path")
}

如何模拟这种情况 class 并覆盖 b 的值?

试试这个:

object abc extends App {
  case class A() {
    val x = 6
  }

  val a: A = new A() {
    override val x = 9
  }

  println(A().x, a.x)
}

来自 scalamock faq:

Can I mock val / lazy val?

No, the Scala compiler will not allow overriding a val with a def, so with ScalaMock this is not possible. An option we are looking at for a possible future version of ScalaMock is scala.meta, but this is not yet available for all build targets we want. If you can, it is better to design a trait with a def and mock that instead. The concrete implementation can still override that def with a val to give invariant behaviour.

如果您将大小写 class 更改为 trait,您可以使用 proxy.MockFactory.

覆盖 val

如果您将 val 更改为 def,您将能够使用普通模拟进行覆盖。

您也可以使用 Raman 的回答中的方法,因此除非您想让 class final 成为可行的解决方案。

但我认为你真正应该做的只是创造特质:

trait InputCriteria {
     def b: Int
}

然后实施它:

case class ConfigDrivenInputCriteria(config: Config) extends InputCriteria {
    override val b: Int = config.getInt("some path")
}

然后在测试中你可以重新实现它:

val testInputCritria = new InputCriteria {
    override def b: Int = 4
}

但如果你在 InputCriteria 中有很多字段,它可能会有点笨拙,但在那种情况下你也可以模拟它:

val inputCriteria = stub[InputCriteria]
(inputCriteria.b _).when().returns(100)

接口+实现方法使您能够轻松测试代码。您还可以在实施 class 时决定您的属性是否应为 defsvalslazy vals.