Scala - 如何执行“assertThrows”方法?

时间:2011-10-23 12:18:36

标签: generics scala

我昨天开始学习Scala,所以我对它很陌生。在学习新语言时,我喜欢做的一件事是尝试创建一个微型TDD库。

这是我到目前为止所得到的:

def assert(condition: Boolean, message: String) {
  if(!condition){ throw new AssertionError(message) }
}

def assertThrows[E](f: => Unit) {
  try {
    f
  } catch {
    case e: E => { return }
    case _: Exception => { }
  }
  throw new AssertionError("Expected error of type " + classOf[E] )
}

assert的代码运行正常,但我遇到了assertThrows的两个问题。

  • 似乎我不能在最后一行使用E。无论我做什么,我都会得到class type expected but E found error
  • 如果我从最后一行删除E(例如,将其替换为throw new AssertionError("error expected")),我会得到:warning: abstract type E in type pattern is unchecked since it is eliminated by erasure

我认为我遇到的两个问题与Scala(可能是java)处理抽象类型的方式有关,以及它们是如何完成的。

如何修复我的assertThrows?

奖励积分:我指定“块类型”(f: => Unit)的方式是正确的吗?

2 个答案:

答案 0 :(得分:8)

Java虚拟机通过类型擦除实现泛型,因此在方法体内,JVM实际上并不知道E的类型,因此AssertThrows方法无法按照您的方式工作。您需要为异常类隐式传递Manifest,如下所示:

def assertThrows[E](f: => Unit)(implicit eType:ClassManifest[E]) {

然后你可以在正文中使用它来捕获异常或获取类名:

  try {
    f
  } catch {
    case e: Exception =>
      if ( eType.erasure.isAssignableFrom(e.getClass))
        return;
  }
  throw new AssertionError("Expected error of type " + eType.erasure.getName )
}

感谢the Spring framework's AssertThrows class告诉我如何执行此操作。

答案 1 :(得分:0)

感谢Ken的回答,我得到了这件事:

class AssertException(msg: String) extends Exception(msg: String)

def assertThrows[E](f: => Unit)(implicit eType:ClassManifest[E]) {
  try{
    f
  } catch {
  case e: Exception =>
    if(eType.erasure.isAssignableFrom(e.getClass)) { return }
  }
  throw new AssertException("Expected error of type " + eType.erasure.getName )
}

/* examples of usage */

assertThrows[NullPointerException]{ throw new NullPointerException() } // ok
assertThrows[AssertException] { assertThrows[Exception]{ } } // ok!

非常感谢!