Scala expected exception fragment

I am trying to model the expected exception behavior for common test frameworks (like JUnit or TestNG).

Here is what I could come up with so far (while working):

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) } } 

The fragment has a main method that executes the code. My problem is that the thrown exception is included in the first pattern matching statement:

 case expected : T 

Although I do say that the exception must be of type T , which would be an IllegalArgumentException .

Any ideas?

0
source share
1 answer

Compile with -unchecked and you will see a warning that a test of type expected: T will always return true, due to type erasure.

 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! 

After seeing how you went through the class, you can use Class#isInstance . In your code, it will look like this:

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

In a separate example. Here we skip Manifest[T] implicitly, which is a way to force the compiler to pass an additional parameter to get information that erases the erase:

 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 

Further reading:

+5
source

Source: https://habr.com/ru/post/899909/


All Articles