1

我想对调用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

4

1 回答 1

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

于 2012-06-22T09:33:12.777 回答