How to start Play application before tests and then shut it down in specs2?

孤人 提交于 2019-12-09 13:32:52

问题


My goal is to get an application running and execute multiple tests on the same instance of the app.

I have tried this solution without much luck. Here is my test:

class ApplicationSpec extends Specification { sequential


  object AppWithTestDb2 extends FakeApplication(additionalConfiguration = 
    Map(
    ("db.default.driver") -> "org.h2.Driver",
    ("db.default.url") -> (
//        "jdbc:h2:mem:play-test-" + scala.util.Random.nextInt +      // in memory database 
        "jdbc:h2:/tmp/play-test-" + scala.util.Random.nextInt +     // file based db that can be accessed using h2-browse in activator
        ";MODE=PostgreSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1")
    ))

    running(AppWithTestDb2) {

      "Application" should {

        "send 404 on a bad request" in {
          route(FakeRequest(GET, "/boum")) must beNone
        }

        "post signup request" in {
          val res = route(FakeRequest(POST, "/user", FakeHeaders(), TestData.newUser)).get
                  status(res) must equalTo(OK)
                  contentType(res) must beSome("application/json")
                  contentAsJson(res) mustEqual TestData.newUser
        }

        "fail signup request for existing user" in {
          val res1 = route(FakeRequest(POST, "/user", FakeHeaders(), TestData.newUser)).get
                  Await.result(res1, Duration.Inf)
                  val res = route(FakeRequest(POST, "/user", FakeHeaders(), TestData.newUser)).get
                  Await.result(res, Duration.Inf)
                  status(res) must equalTo(CONFLICT)
                  contentType(res) must beSome("application/json")
                  contentAsJson(res) mustEqual TestData.newUser
        }

    }
  }

}

The problem here is that application starts and stops immediately and tests are executed without a running application:

[debug] c.j.b.BoneCPDataSource - JDBC URL = jdbc:h2:/tmp/play-test--437407884;MODE=PostgreSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1, Username = zalando, partitions = 1, max (per partition) = 30, min (per partition) = 5, idle max age = 10 min, idle test period = 1 min, strategy = DEFAULT
[info] application - Application has started
[debug] application - Binding to Slick DAO implementations.
[info] application - Application shutdown...
[debug] c.j.b.BoneCPDataSource - Connection pool has been shut down
[info] ApplicationSpec
[info] 
[info] Application should
[info] ! send 404 on a bad request
[error]    RuntimeException: : There is no started application  (Play.scala:71)
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:71)
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:71)
[error] play.api.Play$.current(Play.scala:71)
[error] play.api.test.RouteInvokers$class.route(Helpers.scala:305)
[error] play.api.test.Helpers$.route(Helpers.scala:403)
[error] ApplicationSpec$$anonfun$1$$anonfun$apply$7$$anonfun$apply$8$$anonfun$apply$9.apply(ApplicationSpec.scala:76)
[error] ApplicationSpec$$anonfun$1$$anonfun$apply$7$$anonfun$apply$8$$anonfun$apply$9.apply(ApplicationSpec.scala:76)
[error] ApplicationSpec$$anonfun$1$$anonfun$apply$7$$anonfun$apply$8.apply(ApplicationSpec.scala:76)
[error] ApplicationSpec$$anonfun$1$$anonfun$apply$7$$anonfun$apply$8.apply(ApplicationSpec.scala:76)

回答1:


In specs2 there is a distinction between test declaration and test execution. When you write "application" should ... you just declare tests. The executable part is what is enclosed in the ... in ... part.

So when you declare running(AppWithTestDb2) { ... } you just create some tests inside the context of an AppTestDb2 application.

The general solution for what you want to achieve in specs2 is to use Steps like this:

class ApplicationSpec extends Specification { sequential

  step("start application")

  "Application" should {
    "send 404 on a bad request" in { ... }

    "post signup request" in { ... }
  }

  step("stop application")
}

Then, the way the specs2 execution model works, you will get your fake application started before all the tests start and terminated when all the tests are finished (whether you use sequential or not)

I am not a Play user but I suspect that you should be able to reuse the WithApplication class or something similar to create your start/stop steps. Otherwise there is a blog post here exploring a solution for the same problem.




回答2:


Here is my working solution

object AppWithTestDb2 extends FakeApplication(additionalConfiguration = 
Map(
    ("db.default.driver") -> "org.h2.Driver",
    ("db.default.url") -> (
//        "jdbc:h2:mem:play-test-" + scala.util.Random.nextInt +      // in memory database 
        "jdbc:h2:/tmp/play-test-" + scala.util.Random.nextInt +     // file based db that can be accessed using h2-browse in activator
        ";MODE=PostgreSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1")
))


class SignupLoginSpec extends Specification { sequential


    step(Play.start(AppWithTestDb2))

  "application" should {

    "post signup request" in {
      val res = route(FakeRequest(POST, "/user", FakeHeaders(), TestData.newUser)).get
      status(res) must equalTo(OK)
      contentType(res) must beSome("application/json")
      contentAsJson(res) mustEqual TestData.newUser
    }

    "fail signup request for existing user" in {
      val res1 = route(FakeRequest(POST, "/user", FakeHeaders(), TestData.newUser)).get
      Await.result(res1, Duration.Inf)
      val res = route(FakeRequest(POST, "/user", FakeHeaders(), TestData.newUser)).get
      Await.result(res, Duration.Inf)
      status(res) must equalTo(CONFLICT)
      contentType(res) must beSome("application/json")
      contentAsJson(res) mustEqual TestData.newUser
    }

  }

  step(Play.stop())

}


来源:https://stackoverflow.com/questions/27567512/how-to-start-play-application-before-tests-and-then-shut-it-down-in-specs2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!