Generates JUnit bootstrapper objects for Scala.js.
On the JVM, JUnit uses run-time reflection to list and invoke JUnit-related
methods. They are identified by annotations such as @Test, @Before,
etc. In Scala.js, there is no such reflection for methods and annotations,
so a different strategy is used: this phase performs the necessary
inspections at compile-time, and generates a so-called bootstrapper object
where all those metadata have been reified.
With an example: given the following JUnit test class:
class MyTest {
@Before def myBefore(): Unit = ...
@Before def otherBefore(): Unit = ...
@Test def syncTest(): Unit = ...
@Test def asyncTest(): Future[Try[Unit]] = ...
@Ignore @Test def ignoredTest(): Unit = ...
}
object MyTest {
@AfterClass def myAfterClass(): Unit = ...
}
this phase generates the following bootstrapper module class:
object MyTest$scalajs$junit$bootstrapper extends Object with Bootstrapper {
def beforeClass(): Unit = {
// nothing, since there is no @BeforeClass method in object MyTest
}
def afterClass(): Unit = {
MyTest.myAfterClass()
}
def before(instance: Object): Unit = {
// typically 0 or 1, but also support 2 or more
instance.asInstanceOf[MyTest].myBefore()
instance.asInstanceOf[MyTest].otherBefore()
}
def after(instance: Object): Unit = {
// nothing, since there is no @After method in class MyTest
}
def tests(): Array[TestMetadata] = Array(
new TestMetadata("syncTest", false, new org.junit.Test()),
new TestMetadata("asyncTest", false, new org.junit.Test()),
new TestMetadata("ignoredTest", true, new org.junit.Test()),
)
def invokeTest(instance: Object, name: String): Future[Unit] = {
val castInstance: MyTest = instance.asInstanceOf[MyTest]
if ("syncTest".equals(name))
Future.successful(scala.util.Success(castInstance.syncTest()))
else if ("asyncTest".equals(name))
castInstance.asyncTest() // asyncTest() already returns a Future[Try[Unit]]
else if ("ignoredTest".equals(name))
Future.successful(scala.util.Success(castInstance.ignoredTest()))
else
throw new NoSuchMethodException(name)
}
def newInstance(): Object = new MyTest()
}
Note that the support for test methods returning Futures is specific to
Scala.js, and not advertised as a public feature. It is necessary to test
some things in Scala.js itself, but outside users should use a testing
framework with official asynchronous support instead.
Because Booststrapper is annotated with @EnableReflectiveInstantiation,
the run-time implementation of JUnit for Scala.js can load the bootstrapper
module using scala.scalajs.reflect.Reflect, and then use the methods of
Bootstrapper, which are implemented in the bootstrapper object, to perform
test discovery and invocation.
TODO At the moment, this phase does not handle @Test annotations with
parameters, notably the expected exception class. This should be handled at
some point in the future.
Attributes
- Companion:
- object
- Graph
- Supertypes