3

我正在学习 coursera 中的 scala 课程,并在上一个练习中被要求实施集合操作。我失败的一项测试被称为

存在应该在forall方面执行

exists 和 forall 签名都是:

type Set = Int => Boolean

def forall(s: Set, p: Int => Boolean): Boolean = {}
def exists(s: Set, p: Int => Boolean): Boolean = {

   /*should eventually call forall */
}

我不是要求实现,而是如何在 scala 中执行这样的单元测试

4

2 回答 2

3

我可以想到三种方法开始:

1)模拟forall抛出一个特定的异常,然后调用exists,看看它是否抛出了那个异常。

2)检测代码并调用exists,然后测试是否forall被调用

3) 使用 scala 宏,它分析 ASTexists并递归检查它是否调用forall.

于 2013-10-06T12:21:39.573 回答
2

使用模拟对象很容易做到这一点。我在我的 Java 项目中使用 Mockito,它在 Scala 中也非常有用,尤其是与 Scalatest 一起使用。

将此代码放入project_dir/build.sbt

scalaVersion := "2.10.2"

libraryDependencies ++= Seq(
  "org.scalatest" %% "scalatest" % "2.0.M8",
  "org.mockito" % "mockito-core" % "1.9.5"
)

然后将此代码放入project_dir/src/main/test/test.scala

import org.scalatest.{FlatSpec,ShouldMatchers}
import org.scalatest.mock.MockitoSugar

package object test {
  type Set = Int => Boolean
}

package test {
  class Foraller {
    def forall(s: Set, p: Int => Boolean): Boolean = ???
  }

  class Exister(foraller: Foraller) {
    def exists(s: Set, p: Int => Boolean): Boolean = ???  // Fails
    // def exists(s: Set, p: Int => Boolean): Boolean = foraller.forall(s, p)  // Passes
  }

  class Test extends FlatSpec with ShouldMatchers with MockitoSugar {
    "Exister" should "use Foraller in its exists method" in {

      val foraller = mock[Foraller]

      val exister = new Exister(foraller)

      val set: Set = _ == 1
      val pred: Int => Boolean = _ > 0

      exister.exists(set, pred)

      import org.mockito.Mockito._

      verify(foraller).forall(set, pred)
    }
  }
}

然后调用sbt test中的命令project_dir。您应该看到测试失败了。在课堂上切换评论并重Exister试。

在这里,我们为提供方法的类创建模拟对象,并在提供forall方法的类中使用该对象exists。Mockito 允许验证是否调用了某个模拟对象上的某个方法,这就是这里的工作原理。

于 2013-10-06T18:15:10.350 回答