Scala - How to make assertThrows method?

I started learning Scala yesterday, so I'm pretty new to this. One thing I like to do when learning a new language is to create a micro-TDD library.

This is what I got so far:

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

The code for assert works fine, but I have two problems with assertThrows .

  • It seems that I can not use E in the last line. No matter what I do, I get class type expected but E found error .
  • If I remove E from the last line (for example, replacing it with throw new AssertionError("error expected") ), I get the following: warning: abstract type E in type pattern is unchecked since it is eliminated by erasure

I think the two problems that I have are related to how Scala (and probably java) deals with abstract types and how they are executed.

How can I fix my assertThrows?

Bonus points: is this the way I set the "block type" ( f: => Unit ) correctly?

+6
source share
2 answers

The Java virtual machine implements generics through type erasure, therefore, inside the body of the JVM method, it actually knows nothing about type E, therefore this AssertThrows method cannot work the way you would like. You need to implicitly pass the manifest for your exception class, for example:

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

Then you can use it in the body to catch the exception or get the class name as follows:

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

Thanks to the structure of the Spring AssertThrows class class to show me how to do this.

+8
source

I got this job thanks to 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! 

Thanks a lot!

0
source

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


All Articles