我正在跟踪课程中的scala课程,并且我被要求在上一次练习中实施设置操作。我失败的测试之一被称为
存在应该以forall
来实现
存在和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中执行这样的单元测试
答案 0 :(得分:3)
我可以想到三种方法:
1)模拟forall
抛出特定异常,然后调用exists
,看看是否抛出该异常。
2)检测代码并调用exists
,然后进行测试,看看是否调用了forall
3)使用scala宏,它分析exists
的AST并递归检查它是否调用forall
。
答案 1 :(得分:1)
使用模拟对象可以轻松完成。我在我的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允许验证某个模拟对象上的某个方法是否被调用,这就是在这里工作的。