2011-10-08 61 views
0

我試圖模擬常見測試框架(例如JUnit或TestNG)的預期異常行爲。斯卡拉預計異常片段

這是我能想出這麼遠(工作):

trait ExpectAsserts 
{ 
    self : { 
    def fail (message : String) 
    def success (message : String) 
    } => 

    def expect[T](exceptionClass : Class[T])(test : => Unit) 
    { 
    try 
    { 
     test 
     fail("exception not thrown") 
    } 
    catch 
    { 
     case expected : T => success("got exception " + expected) 
     case other : Exception => fail("expected "+ exceptionClass + " but " + other + " thrown instead.") 
    } 
    } 
} 

object Main extends ExpectAsserts 
{ 
    def main (args : Array[String]) 
    { 
    expect(classOf[ArithmeticException]) 
    { 
     throw new IllegalArgumentException // this should print an error message. 
    } 
    } 

    def fail (s : String) 
    { 
    System.err.println(s) 
    } 

    def success(s : String) 
    { 
    System.out.println(s) 
    } 
} 

代碼段有一個main方法分析代碼。我的問題是,拋出的異常的第一圖案匹配的語句進入:

case expected : T 

雖然我實際上說的異常必須是T型,這將是IllegalArgumentException的。

任何想法?

回答

5

-unchecked編譯,你會看到一個警告,型式測試expected: T總是返回true,由於類型擦除。

scala> def foo[T](a: Any) = a match { 
    | case _: T => "always will match!" 
    | } 
<console>:22: warning: abstract type T in type pattern T is unchecked since it is eliminated by erasure 
      case _: T => "always will match!" 
       ^
foo: [T](a: Any)java.lang.String 

scala> foo[String](0) 
res3: java.lang.String = always will match! 

看到有您的類傳入您可以使用Class#isInstance代替。在您的代碼中,這看起來像:

case expected if clazz.isInstance(expected) => success("got exception " + expected) 

在一個自包含的示例中。下面我們通過一個Manifest[T]含蓄,這是一種方式來獲得編譯器將一個額外的參數,以獲得該類型擦除扔掉信息:

scala> def foo[T: ClassManifest](a: Any) = manifest[T].erasure.isInstance(a) 
foo: [T](a: Any)(implicit evidence$1: Manifest[T])Boolean 

scala> foo[String](new {}) // compiler passes Manifest[String] here 
res4: Boolean = false 

scala> foo[String]("") 
res5: Boolean = true 

延伸閱讀:

+0

非常感謝你的提示 –