When I run tests with scalaTestPlus and Play framework, I get an error "no started application" - scala

I'm trying to make scalaTestPlus work in my play application (I'm using Play! 2.2). It works well until I need a function coming from my application. For instance, if I run this very simple test (by launching in a sbt console "test-only TestName"):
import org.scalatestplus.play._
import org.scalatest._
import Matchers._
class Test extends PlaySpec {
"This test" must {
"run this very simple test without problem" in {
1 mustEqual 1
}
}
}
There is no problem, but as soon as I call a function from my app, like in this code:
class Test extends PlaySpec {
"This test" must {
"run this very simple test without problem" in {
models.Genre.genresStringToGenresSet(Option("test")) //Here is the problem
1 mustEqual 1
}
}
}
I get an error: java.lang.ExceptionInInitializerError: at... Cause: java.lang.RuntimeException: There is no started application (even if my application is running).
I'm probably missing something simple since I'm brand new to ScalaTest, so any help abut what I'm doing wrong would be apreciated ;)

You may need an application in scope when using PlaySpec, as some operations assume that there is a Play application available via Play.current:
class Test extends PlaySpec {
implicit override lazy val app: FakeApplication = FakeApplication(...)
"This test" must {
"run this very simple test without problem" in {
models.Genre.genresStringToGenresSet(Option("test")) //Here is the problem
1 mustEqual 1
}
}
}
Check the functional testing documentation for more details on FakeApplication.
However, I don't think you need should need this for model testing. In the normal ScalaTest docs for play, it seems to just mix inMockitoSugar. But your method call chain may invoke some global state of Play that does require an Application, in which case the FakeApplication is the way to go

As asked by #akauppi, here is a method that works perfectly for me:
import org.scalatestplus.play.{OneAppPerSuite, PlaySpec}
class A extends PlaySpec with OneAppPerSuite {
"a" must {
"return true" in {
//thanks to with OneAppPerSuite, it now works
models.Genre.genresStringToGenresSet(Option("test"))
1 mustBe 1
}
"return false" in {
1 mustBe 2
}
}
}
And I simply launch the test with sbt ~testOnly a

Related

Embedding multiple tests inside an akka-http route check

I'm using akka-http for the first time - my usual web framework of choice is http4s - and I'm having trouble getting the way I usually write endpoint unit tests to work with the route testing provided by akka-http-testkit.
Generally, I use ScalaTest (FreeSpec flavour) in order to set up an endpoint call and then run several separate tests on the response. For akka-http-testkit, this would look like:
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.{FreeSpec, Matchers}
final class Test extends FreeSpec with ScalatestRouteTest with Matchers {
val route: Route = path("hello") {
get {
complete("world")
}
}
"A GET request to the hello endpoint" - {
Get("/hello") ~> route ~> check {
"should return status 200" in {
status should be(StatusCodes.OK)
}
"should return a response body of 'world'" in {
responseAs[String] should be("world")
}
//more tests go here
}
}
}
This errors with
java.lang.RuntimeException: This value is only available inside of a `check` construct!
The problem is the nested tests inside the check block - for some reason, values like status and responseAs are only available top-level within that block. I can avoid the error by saving the values I'm interested in to local variables top-level, but that's awkward and capable of crashing the test framework if e.g. the response parsing fails.
Is there a way around this, without putting all my assertions into a single test or performing a new request for each one?
You can group your test like that
"A GET request to the hello endpoint should" in {
Get("/hello") ~> route ~> check {
status should be(StatusCodes.OK)
responseAs[String] should be("world")
//more tests go here
}
}

fail to load a native library using activator (Play Framework)

I'm trying to load a native library in my Play 2.4.x application. I have written a simple test that works fine both in the IDE (IntelliJ) and in SBT. In both case I'm setting the java.library.path to get the tests to run.
In the IDE, I set -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 in the test run configuration.
As per the sbt documentation, my build.sbt is forking the JVM and setting the java.library.path.
javaOptions += "-Djava.library.path=/home/aczerwon/dev/lindoapi/bin/linux64"
fork := true
The following test passes just fine in both the IDE and from activator test.
class LindoApiSpec extends Specification {
System.loadLibrary("lindojni")
"The Lindo API" should {
"have a valid license" in {
val lindo = new LindoEnvironment()
lindo.apiVerion() must beSuccessfulTry.withValue("LINDO API Version 9.0.2120.225")
}
}
When outside of the testing context, I load the native library in Play's startup lifecycle.
object Global extends GlobalSettings {
override def beforeStart(app: Application) = {
System.loadLibrary("lindojni")
}
}
When I call that same method from the webapi (activator ~run), I'm getting an UnsatisfiedLinkError error.
1) Error injecting constructor, java.lang.UnsatisfiedLinkError: no lindojni in java.library.path
at play.api.GlobalPlugin.<init>(GlobalSettings.scala:262)
at play.api.GlobalPlugin.class(GlobalSettings.scala:262)
while locating play.api.GlobalPlugin
The web api looks like this:
class OptimizationApi extends Controller {
def version() = Action {
val lindo = new LindoEnvironment()
lindo.apiVerion() match {
case Success(version) => Ok(version)
case Failure(e) => BadRequest(e.getMessage)
}
}
}
I assumed that my build.sbt would fork the JVM and set the java.library.path for both test and run contexts. Any clues as to what I'm doing wrong?
New Information
When I start activator -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 or set JAVA_OPTS, the call to System.loadLibrary(...) in the startup lifecycle passes. I still get the UnsatisfiedLinkError, but it happens later when I make a call to the native library via JNI. Very strange.
I found a solution to the issue here.
The native library and its java counterpart must be in the same class loader.
Create a class similar to:
public final class PlayNativeLibraryLoader {
public static void load(String libraryPath) {
System.load(libraryPath);
}
}
And now you can use it in the Play startup lifecycle.
object Global extends GlobalSettings {
override def beforeStart(app: Application) = {
PlayNativeLibraryLoader.load(app.getFile("./lib/lindoapi/linux64/liblindojni.so").getPath)
Logger.info("Lindo native library loaded")
}
}

No JUnit tests found in Eclipse using Groovy + Cucumber

I have a Cucumber test in Groovy as follows
import org.junit.runner.RunWith
import cucumber.junit.Cucumber
import cucumber.junit.Cucumber.Options
#RunWith(Cucumber.class)
#Options(features = ["classpath:CarDrive.feature"])
public class FuelCarTest {
}
import cucumber.annotation.en.Given
import cucumber.annotation.en.Then
import cucumber.annotation.en.When
public class FuelCarSteps {
public FuelCarSteps() {
println "FuelCarSteps::FuelCarSteps"
}
#Given("I have a car")
def givenCar() {
println "I have a car"
}
#When("^you fill it with 50 litres of fuel")
def addFuel() {
println "add fuel"
}
#Then("^the tank contains 60 litres")
def checkBalance() {
println "TODO: add check here"
}
}
I can run the test fine using mvn test, but when I try to run it in Eclipse I get
No JUnit tests found
Tried cleaning, rebuilding & restarting
Hi you need to create run configuration for the each test in junit
Provide full path ( like package1.subpackege1.testclassname ) in class input in run config
Control, if you have any errors in the Groovy code, such as Type of expression is statically unknown: or similar. They don't show off as usual errors and could be almost invisible.

Specs2: Ignore specification with a message?

I need to put one of my test cases into a "pending" state.
I would like to assing some sort of message to it that can be displayed on the output when running the test, something like JUnit with #Ignore("Pending: issue #1234 needs to be fixed").
Is there an equivalent for that with Specs2?
class MySpec extends mutable.Specification {
args(skipAll = true) // Can I include a message here in the output somehow?
"cool MyClass feature" should {
"which is broken unfortunately" in {
failure
}
}
}
Thanks in advance!
For an individual example, I believe you can use:
class MySpec extends mutable.Specification {
"cool MyClass feature" should {
"which is broken unfortunately" in {
failure
}.pendingUntilFixed("message about the issue")
}
}
I don't know if there's a way to extend this to mark all the examples in a spec as pending with the same message, as you seem to be hoping.

is there a scalaTest mechanism similar to TestNg dependsOnMethods annotation

Can I have dependencies between scalaTest specs such that if a test fails, all tests dependent on it are skipped?
I didn't add that feature of TestNG because I didn't at the time have any compelling use cases to justify it. I have since collected some use cases, and am adding a feature to the next version of ScalaTest to address it. But it won't be dependent tests, just a way to "cancel" a test based on an unmet precondition.
In the meantime what you can do is simply use Scala if statements to only register tests if the condition is met, or to register them as ignored if you prefer to see it output. If you are using Spec, it would look something like:
if (databaseIsAvailable) {
it("should do something that requires the database") {
// ...
}
it ("should do something else that requires the database") {
}
}
This will only work if the condition will be met for sure at test construction time. If the database for example is supposed to be started up by a beforeAll method, perhaps, then you'd need to do the check inside each test. And in that case you could say it is pending. Something like:
it("should do something that requires the database") {
if (!databaseIsAvailable) pending
// ...
}
it("should do something else that requires the database") {
if (!databaseIsAvailable) pending
// ...
}
Here is a Scala trait that makes all test in the test suite fail, if any test fails.
(Thanks for the suggestion, Jens Schauder (who posted another answer to this question).)
Pros: Simple-to-understand test dependencies.
Cons: Not very customizable.
I use it for my automatic browser tests. If something fails, then usually there's no point in continuing interacting with the GUI since it's in a "messed up" state.
License: Public domain (Creative Common's CC0), or (at your option) the MIT license.
import org.scalatest.{Suite, SuiteMixin}
import scala.util.control.NonFatal
/**
* If one test fails, then this traits cancels all remaining tests.
*/
trait CancelAllOnFirstFailure extends SuiteMixin {
self: Suite =>
private var anyFailure = false
abstract override def withFixture(test: NoArgTest) {
if (anyFailure) {
cancel
}
else try {
super.withFixture(test)
}
catch {
case ex: TestPendingException =>
throw ex
case NonFatal(t: Throwable) =>
anyFailure = true
throw t
}
}
}
I don't know about a ready made solution. But you can fairly easily write your own Fixtures.
See "Composing stackable fixture traits" in the javadoc of the Suite trait
Such a fixture could for example replace all test executions after the first one with calls to pending
You can use trait org.scalatest.CancelAfterFailure to cancel remaining tests after first failure:
import org.scalatest._
class MySpec extends FunSuite with CancelAfterFailure {
test("successfull test") {
succeed
}
test("failed test") {
assert(1 == 0)
}
test("this test and all others will be cancelled") {
// ...
}
}