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 Future
s 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