Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala - How do I do an "assertThrows" method?

Tags:

generics

scala

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

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 just fine, but I'm having two problems with assertThrows.

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

I think that the two problems I'm having are related with the way Scala (and probably java) deals with abstract types, and how are they done.

How can I fix my assertThrows?

Bonus points: is the way I'm specifying a "block type" (f: => Unit) correct ?

like image 865
kikito Avatar asked Oct 23 '11 12:10

kikito


People also ask

Which testing framework have you used for Scala?

ScalaTest is one of the most popular, complete and easy-to-use testing frameworks in the Scala ecosystem.

How to use assert in Scala?

assert is a precondition in Scala that evaluates a boolean expression as true or false. It's generally used to validate the execution of the program during runtime. We can see assert is used commonly in testing the functionality of programs.


1 Answers

The Java virtual machine implements generics through type erasure, so inside the method body the JVM doesn't actually know anything about what type E is, so this AssertThrows method can't work the way you'd like. You need to implicitly pass a Manifest for your exception class, like so:

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 like so:

  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 Spring framework's AssertThrows class for showing me how to do this.

like image 72
Ken Bloom Avatar answered Oct 09 '22 20:10

Ken Bloom