How to use ScriptEngine in ScalaTest

You need to explicitly pass in a ClassLoader to the ScriptEngineManager constructor. If you don't then it uses Thread.currentThread().getContextClassLoader() which is set to something weird when running under SBT. We just pass in null in our code to get it to work. You can also pass in getClass.getClassLoader:

class EngineTest extends FunSuite {
  test("engine should not be null - null classloader") {
    val manager: ScriptEngineManager = new ScriptEngineManager(null)
    val engine: ScriptEngine = manager.getEngineByName("nashorn")
    assert(engine != null)
  }

  test("engine should not be null - getClass.getClassLoader classloader") {
    val manager: ScriptEngineManager = new ScriptEngineManager(getClass.getClassLoader)
    val engine: ScriptEngine = manager.getEngineByName("nashorn")
    assert(engine != null)
  }
}

Both of those tests pass for me:

[info] EngineTest:
[info] - engine should not be null - null classloader
[info] - engine should not be null - getClass.getClassLoader classloader
[info] Run completed in 186 milliseconds.
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

What versions are you using? This is sbt .13.

> console
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.11.0 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import javax.script._
import javax.script._

scala> new ScriptEngineManager().getEngineByName("scala")
res0: javax.script.ScriptEngine = scala.tools.nsc.interpreter.IMain@7078c799

scala> new ScriptEngineManager().getEngineByName("rhino")
res1: javax.script.ScriptEngine = com.sun.script.javascript.RhinoScriptEngine@5c854934

scala> new ScriptEngineManager().getEngineFactories
res2: java.util.List[javax.script.ScriptEngineFactory] = [com.sun.script.javascript.RhinoScriptEngineFactory@454ee4c0, scala.tools.nsc.interpreter.IMain$Factory@354e3bce]

Wait, you asked about test context --

Well, before I lost interest in decoding more sbt, adding to libraryDependencies:

"org.scala-lang" % "scala-compiler" % scalaVersion.value % "test",

enables locating the Scala script engine:

  @Test def engines: Unit = {
    import javax.script._
    val all = new ScriptEngineManager().getEngineFactories
    Console println s"Found ${all.size}: $all"
    assert(all.size > 0)
  }

No doubt there's a simple way to add runtime:full-classpath to test:full-classpath directly. Because it's the simple build tool, right?

For Nashorn on Java 8, note the location:

> set fullClasspath in Test += Attributed.blank(file(s"${util.Properties.javaHome}/lib/ext/nashorn.jar"))
[info] Defining test:fullClasspath
[info] The new value will be used by test:console, test:executeTests and 5 others.
[info]  Run `last` for details.
[info] Reapplying settings...
[info] Set current project to goofy (in build file:/home/apm/goofy/)
> test
Found 1: [jdk.nashorn.api.scripting.NashornScriptEngineFactory@7fa2239d]
[info] Passed: Total 10, Failed 0, Errors 0, Passed 10

Update: https://github.com/sbt/sbt/issues/1214

Also I guess it's still considered black art:

// Somehow required to get a js engine in tests (https://github.com/sbt/sbt/issues/1214)

fork in Test := true