我想测试一个在其中调用error()
的方法。
IntEmptyStack.top
是我想用specs2测试的:
abstract class IntStack {
def push(x: Int): IntStack = new IntNonEmptyStack(x, this)
def isEmpty: Boolean
def top: Int
def pop: IntStack
}
class IntEmptyStack extends IntStack {
def isEmpty = true
def top = error("EmptyStack.top")
def pop = error("EmptyStack.pop")
}
这是我到目前为止所写的规格:
import org.junit.runner.RunWith
import org.specs2.runner.JUnitRunner
import org.specs2.mutable.Specification
@RunWith(classOf[JUnitRunner])
class IntStackSpec extends Specification {
"IntEmptyStack" should {
val s = new IntEmptyStack
"be empty" in {
s.isEmpty must equalTo(true)
}
"raise error when top called" in {
s.top must throwA[RuntimeException]
}
}
}
错误发生在第13行"raise error when top called" in {
。错误消息为value must is not a member of Nothing
。我认为Scala将s.top
推断为Nothing,而不是抽象类中定义的Int。在这种情况下,如何在没有任何错误的情况下编写测试?
感谢您对此问题的任何评论/更正。
示例参考:Scala By Example
答案 0 :(得分:5)
这里的问题是scala(和Java)允许子类在重写方法中返回比超类更具体的类型。在这种情况下,您的方法IntEmptyStack.top
的返回类型为Nothing
(Int
的子类型,因为Nothing
位于类型层次结构。
当a must throwA[X]
的类型为a
Nothing
等代码所需的隐式转换显然不适用
更改IntEmptyStack
中的声明,如下所示:
def top: Int = error("EmptyStack.top")
def pop: Int = error("EmptyStack.pop")
或者,当然,您可以允许逻辑的正确性被类型系统 验证。也就是说,不可能获得位于空堆栈顶部的元素:返回类型为Nothing
!不需要进行任何测试。