模拟案例类进行测试

Sha*_*nga 0 scala scalatest scalamock

我有一个案例课

case class InputCriteria(a: Int) {
   val b: Int = config.getInt("some path")
}
Run Code Online (Sandbox Code Playgroud)

如何模拟这个案例类并覆盖 b 的值?

Krz*_*sik 5

来自 scalamock常见问题解答

我可以模拟 val/lazy val 吗?

不,Scala 编译器不允许用 def 覆盖 val,所以对于 ScalaMock 这是不可能的。我们正在寻找 ScalaMock 未来版本的一个选项是 scala.meta,但这还不适用于我们想要的所有构建目标。如果可以的话,最好用 def 设计一个特征并模拟它。具体实现仍然可以用 val 覆盖该 def 以提供不变的行为。

如果您将案例类更改为trait您可以val使用proxy.MockFactory进行覆盖。

如果你改变你valdef你就可以用简单的模拟覆盖。

您也可以使用拉曼答案中的方法,因此除非您想让您的课程成为final有效的解决方案。

但在我看来,你真正应该做的就是创造特质:

trait InputCriteria {
     def b: Int
}
Run Code Online (Sandbox Code Playgroud)

然后实施它:

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

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

val testInputCritria = new InputCriteria {
    override def b: Int = 4
}
Run Code Online (Sandbox Code Playgroud)

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

val inputCriteria = stub[InputCriteria]
(inputCriteria.b _).when().returns(100)
Run Code Online (Sandbox Code Playgroud)

接口+实现方法使您能够轻松测试代码。您还可以在实现类时决定您的属性是否应该是defsvals还是惰性 vals

  • 你是对的,该特征存在的唯一原因是为了更容易测试。但在我看来,付出这个代价是值得的,因为这样模拟依赖关系就简单多了。 (2认同)