Play2 Specs2 - 破坏FakeApplication

时间:2016-02-16 15:22:38

标签: scala playframework specs2

我有一系列Specs2测试文件,每个文件都有以下形式:

class NetworkToolsIT extends PlaySpecification {
  sequential

  val databaseName = "xxxx"
  val addConf = Map(...)
  val application = FakeApplication(additionalConfiguration = addConf)
  val server = TestServer(port = 8888, application)

  step(server.start())
  step(resetDB(databaseName))

  "My test" should {
    "test 1" in {
      ...
    }

    "test 2" in {
      ...
    }
  }

  step(server.stop())
}

我的问题是如果我单独运行每个specs2文件,它们都会成功。相反,将它们一起运行(使用sbt test)它们会失败。

这个问题与我使用单例对象作为DAO这一事实有关(如本post中所述)

我想知道在测试完成后是否有办法明确销毁FakeApplication,以便执行不同的测试文件,就好像它们是单独运行一样。

我尝试将其添加到我的项目配置中,但它没有用。

parallelExecution in Test := false

我还尝试在每个测试文件的末尾添加它:

step(play.api.Play.stop())

但没有工作。

P.S。我正在使用Play! 2.3.7

1 个答案:

答案 0 :(得分:0)

您有三种选择:

使用内置的WithServer scope

class NetworkToolsIT extends PlaySpecification {

    sequential

    val serverPort = 8888
    val databaseName = "xxxx"
    val addConf = Map(...)

    step(resetDB(databaseName))

    "My test" should {
        "test 1" in new WithServer(app = FakeApplication(additionalConfiguration = addConf), port = serverPort) {
            ...
        }

        "test 2" in new WithServer(app = FakeApplication(additionalConfiguration = addConf), port = serverPort) {
            ...
        }
    }
}

所以Play会自动处理服务器启动/停止。

使用您自己的BeforeAfterAll specs2 scope

如果您只想为此套件添加一个TestServer,建议使用此选项:

class NetworkToolsIT extends PlaySpecification with BeforeAfterAll {

    val serverPort = 8888
    val databaseName = "xxxx"
    val addConf = Map(...)

    val server = TestServer(port = serverPort, application)

    override def beforeAll = {
      resetDB(databaseName)
      server.start()
    }

    override def afterAll = {
      server.stop()
    }

    "My test" should {
        "test 1" in {
            ...
        }

        "test 2" in {
            ...
        }
    }
}

我在这里假设您不必为每个规范重置数据库,因此对于此套件只能执行一次。此外,您无需在sequential中运行此处的步骤。

使用临时端口到TestServer

这是基于James Roper的this comment

  

当您使用端口号0时,对套接字API说“选择一个免费的临时端口”。这是正常情况下,当你建立客户端连接 - 你指定远程端口,但你说本地端口是0,然后操作系统分配是自由端口(TCP由任何尚未定义的端口定义)用于与该远程IP /端口通信以用于该连接。但是,您也可以在绑定服务器套接字时使用它。绑定服务器套接字后,您可以询问套接字API绑定的端口。

因此,您可以使用端口TestServer更改所有测试以实例化0,如下所示:

class NetworkToolsIT extends PlaySpecification with BeforeAfterAll {

     val serverPort = 0
     val databaseName = "xxxx"
     val addConf = Map(...)

     val server = TestServer(port = serverPort, application)

     override def beforeAll = {
       resetDB(databaseName)
       server.start()
     }

     override def afterAll = {
       server.stop()
     }

     "My test" should {
         "test 1" in {
             val assignedPort = server.port
             ...
         }

         "test 2" in {
             val assignedPort = server.port
             ...
         }
     }
 }

这样,所有测试都可以并行运行而不会发生端口冲突。