I sorted out an article about how to correctly test exceptions in JUnit 4 years ago. A similar question: how to test exceptions in Scala? Scala can fully adopt the JUnit test case style, so of course we can use three Java methods to test exceptions, that is
Try {code to be tested; fail ()} catch (some exception) {asserted}
@
Test (expected = Exception. class) @ Rule
Back in Scala, I am not so willing to use the JUnit @ Test def testMethod () Test method style in Scala, but rather the BDD or DSL style.
Let's take a look at some of Scala's unique exception testing methods.
I. intercept
Import org. scalatest. flatSpec class ScalaExceptionTest extends FlatSpec {"An empty Set" shocould "produce NoSuchElementException when head is invoked" in {intercept [NoSuchElementException] {Set. empty. head }}} test result scala-intercept
Open the source code of the intercept method, which is actually the try-catch method. The source code of the intercept method is as follows:
Def intercept [T <: AnyRef] (f: => Any) (implicit manifest: Manifest [T]): T = {val clazz = manifest. erasure. asInstanceOf [Class [T] val caught = try {f None} catch {case u: Throwable => {if (! Clazz. isAssignableFrom (u. getClass) {val s = Resources ("wrongException", clazz. getName, u. getClass. getName) throw newAssertionFailedException (Some (s), Some (u), 4)} else {Some (u )}}} caught match {case None => val message = Resources ("exceptionExpected", clazz. getName) throw newAssertionFailedException (Some (message), None, 4) case Some (e) => e. asInstanceOf [T] // I know this cast will succeed, becuase isAssignableFrom succeeded above} The intercept () method returns the exception currently thrown, therefore, we can make a more detailed asserted val s = "hi" val thrown = intercept [IndexOutOfBoundsException] {s. charAt (-1)} assert (thrown. getMessage = "String index out of range:-1 ")
II. thrownBy
Import org. scalatest. {MustMatchers, WordSpec} class ScalaExceptionTest extends WordSpec with MustMatchers {"An empty Set produce NoSuchElementException when head is invoked" in {a [condition] must be thrownBy {Set. empty. the description after the head is executed is [info] ScalaExceptionTest: [info]-An empty Set produce NoSuchElementException when head is invoked [info] ScalaTest [info] Run completed in 1 second, 247 milliseconds. [info] Total number of tests run: 1 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed.
That is, the execution code in {} does not help from the description, although it looks pretty good.
The implementation of thrownBy is the same as intercept.
The first generation of specs can use the throwA/throwAn method, now go to specs2, specs has stopped development, find an example from https://code.google.com/p/specs:
"A full stack"->-(fullStack) shocould {behave like "A non-empty stack below full capacity" "throw an exception when sent # push" in {stack. push (11) must throwAn [Error]}
Scala's Java style is basically the same as how JUnit 4 correctly tests the usage in exceptions. The try-catch method only has syntax differences.
Import org. junit. assert. _ import org. junit. test class ScalaExceptionTest {@ Test def testInvokeHeadOnEmptySet: Unit = {try {Set. empty. head fail ("nothing thrown")} catch {case err: NoSuchElementException => // test success case t: Throwable => fail (s "caught $ {t. getClass. getName} instead of NoSuchElementException ")}}}
In short, Scala-style exception tests are intercept and thrownBy.