Getting started with JUnit 4 and Scala

If you want to write JUnit 4 tests in Scala that you run with JUnit, you can enjoy more concise code by using ScalaTest's assertions and/or matchers. To use assertions, mix org.scalatest.junit.AssertionsForJUnit into your test class:

import org.scalatest.junit.AssertionsForJUnit
import scala.collection.mutable.ListBuffer
import org.junit.Assert._
import org.junit.Test
import org.junit.Before

class ExampleSuite extends AssertionsForJUnit {

  var sb: StringBuilder = _
  var lb: ListBuffer[String] = _

  @Before def initialize() {
    sb = new StringBuilder("ScalaTest is ")
    lb = new ListBuffer[String]
  }

  @Test def verifyEasy() { // Uses JUnit-style assertions
    sb.append("easy!")
    assertEquals("ScalaTest is easy!", sb.toString)
    assertTrue(lb.isEmpty)
    lb += "sweet"
    try {
      "verbose".charAt(-1)
      fail()
    }
    catch {
      case e: StringIndexOutOfBoundsException => // Expected
    }
  }

  @Test def verifyFun() { // Uses ScalaTest assertions
    sb.append("fun!")
    assert(sb.toString === "ScalaTest is fun!")
    assert(lb.isEmpty)
    lb += "sweeter"
    intercept[StringIndexOutOfBoundsException] {
      "concise".charAt(-1)
    }
  }
}
Note: JUnit traditionally differentiated between exceptions resulting from assertions, which it called failures, and unexpected exceptions, which it called errors. Although this JUnit 3 distinction was dropped from JUnit 4, many tools that integrate JUnit 4 still observe the distinction. By mixing in org.scalatest.junit.AssertionsForJUnit, you ensure JUnit tools will report failures of ScalaTest assertions as failures not errors.

You can see the difference in conciseness between the JUnit assertions used by verifyEasy and the ScalaTest assertions used by verifyFun. If you compile this class with the Scala compiler, JUnit will happily run the resulting class file. Here's how you compile it:

scalac -cp scalatest-3.0.1.jar:junit-4.4.jar ExampleSuite.scala

Here's one way to run it using JUnit:

$ scala -cp .:scalatest-3.0.1.jar:junit-4.4.jar org.junit.runner.JUnitCore ExampleSuite
JUnit version 4.4
..
Time: 0.046

OK (2 tests)

If you wish to give yourself the option of running with either JUnit or ScalaTest, mix in org.scalatest.junit.JUnitSuite. Trait JUnitSuite already mixes in AssertionsForJUnit:

import org.scalatest.junit.JUnitSuite
import scala.collection.mutable.ListBuffer
import org.junit.Assert._
import org.junit.Test
import org.junit.Before

class ExampleSuite extends JUnitSuite {

  var sb: StringBuilder = _
  var lb: ListBuffer[String] = _

  @Before def initialize() {
    sb = new StringBuilder("ScalaTest is ")
    lb = new ListBuffer[String]
  }

  @Test def verifyEasy() { // Uses JUnit-style assertions
    sb.append("easy!")
    assertEquals("ScalaTest is easy!", sb.toString)
    assertTrue(lb.isEmpty)
    lb += "sweet"
    try {
      "verbose".charAt(-1)
      fail()
    }
    catch {
      case e: StringIndexOutOfBoundsException => // Expected
    }
  }

  @Test def verifyFun() { // Uses ScalaTest assertions
    sb.append("fun!")
    assert(sb.toString === "ScalaTest is fun!")
    assert(lb.isEmpty)
    lb += "sweeter"
    intercept[StringIndexOutOfBoundsException] {
      "concise".charAt(-1)
    }
  }
}

Because ExampleSuite is still a valid JUnit test class, it can still be run with JUnit:

$ scala -cp .:scalatest-3.0.1.jar:junit-4.4.jar org.junit.runner.JUnitCore ExampleSuite
JUnit version 4.4
..
Time: 0.121

OK (2 tests)

But because it is also a ScalaTest Suite, you can now also run it with ScalaTest:

$ scala -cp scalatest-3.0.1.jar:junit-4.4.jar org.scalatest.run ExampleSuite
Run starting. Expected test count is: 2
ExampleSuite:
- verifyFun
- verifyEasy
Run completed in 190 milliseconds.
Total number of tests run: 2
Suites: completed 1, aborted 0
Tests: succeeded 2, failed 0, ignored 0, pending 0
All tests passed.

One final variation you may wish to try is to use ScalaTest's matchers DSL. Simply mix in ShouldMatchersForJUnit (or MustMatchersForJUnit if you prefer "must" to "should"). Here's an example:

import org.scalatest.junit.JUnitSuite
import org.scalatest.junit.ShouldMatchersForJUnit
import scala.collection.mutable.ListBuffer
import org.junit.Test
import org.junit.Before

class ExampleSuite extends JUnitSuite with ShouldMatchersForJUnit {

  var sb: StringBuilder = _
  var lb: ListBuffer[String] = _

  @Before def initialize() {
    sb = new StringBuilder("ScalaTest is ")
    lb = new ListBuffer[String]
  }

  @Test def verifyEasy() { // Uses ScalaTest assertions
    sb.append("easy!")
    assert(sb.toString === "ScalaTest is easy!")
    assert(lb.isEmpty)
    lb += "sweet"
    intercept[StringIndexOutOfBoundsException] {
      "concise".charAt(-1)
    }
  }

  @Test def verifyFun() { // Uses ScalaTest matchers
    sb.append("fun!")
    sb.toString should be ("ScalaTest is fun!")
    lb should be ('empty)
    lb += "sweet"
    evaluating { "concise".charAt(-1) } should produce [StringIndexOutOfBoundsException]
  }
}

As before, you can run this class with either JUnit or ScalaTest:

$ scala -cp .:scalatest-3.0.1.jar:junit-4.4.jar org.junit.runner.JUnitCore ExampleSuite
JUnit version 4.4
..
Time: 0.136

OK (2 tests)

$ scala -cp scalatest-3.0.1.jar:junit-4.4.jar org.scalatest.runner ExampleSuite
Run starting. Expected test count is: 2
ExampleSuite:
- verifyFun
- verifyEasy
Run completed in 182 milliseconds.
Total number of tests run: 2
Suites: completed 1, aborted 0
Tests: succeeded 2, failed 0, ignored 0, pending 0
All tests passed.

ScalaTest is brought to you by Bill Venners and Artima.
ScalaTest is free, open-source software released under the Apache 2.0 license.

If your company loves ScalaTest, please consider sponsoring the project.

Copyright © 2009-2016 Artima, Inc. All Rights Reserved.

artima