Play Famework 2-Scala-为测试套件启动一个应用程序

Play Famework 2-Scala-为测试套件启动一个应用程序,scala,playframework,specs2,Scala,Playframework,Specs2,我一直在使用官方播放文档中的Specs2跟踪Scala测试示例。我注意到他们使用WithApplication启动一个假应用程序进行测试,clode如下所示: "something" should { "do X" in new WithApplication { /* ... */ } "do Y" in new WithApplication { /* ... */ } "do Z" in new WithApplication { /* ... */ } } 这很

我一直在使用官方播放文档中的Specs2跟踪Scala测试示例。我注意到他们使用
WithApplication
启动一个假应用程序进行测试,clode如下所示:

"something" should {
    "do X" in new WithApplication { /* ... */ }
    "do Y" in new WithApplication { /* ... */ }
    "do Z" in new WithApplication { /* ... */ }
}
这很好,但我遇到的问题是,每次发生这种情况时,我都要承担启动应用程序的成本。当您的测试套件增长到合理的大小时,这不一定“快”,或者至少不够快。我试过做一些事情,比如:

val app = FakeApplication()
"something" should {
    "do X" in new WithApplication(app) { /* ... */ }
    "do Y" in new WithApplication(app) { /* ... */ }
    "do Z" in new WithApplication(app) { /* ... */ }
}

第一个似乎适用于第一个测试,然后在以后的测试中抱怨db连接问题。我猜这里有什么东西被关闭了,或者什么东西(不确定是什么)

第二个根本不起作用,因为它抱怨没有正在运行的应用程序,对此我也不确定


非常感谢您的帮助。谢谢

这取决于你想测试什么。如果您只是单元测试没有外部依赖项或可以模拟或剔除的依赖项的代码(最好以允许这种情况的方式构造代码),那么您不需要对应用程序使用
。这可能是最好的办法

您提供的第一个解决方案不起作用,因为应用程序只能使用一次。正是应用程序的
启动和停止了应用程序,所以即使这样做有效,您也不会获得任何性能优势

您提供的第二个解决方案不起作用,因为当
Helpers.running(app){}
代码块运行时,这只是声明规范。Specs将所有这些都放在一个列表中,然后您退出运行块,它将关闭应用程序。然后在某个时候,specs运行测试,当然那时没有应用程序


因此,如果你不能独立于应用程序的其余部分来测试你的代码,那么你需要一个正在运行的应用程序,对此你无能为力,这就是集成测试的现实。您可能希望它在每次测试之间启动和关闭,否则您的测试不会彼此隔离运行。

它已经过时,但我会给出我的答案。因为我面临着同样的问题,有着相似的想法。spec2中有前后特性,可能在发布时不存在,所以我的解决方案基本上是:

package com.equipx.spec.util

import org.specs2.specification.{AfterAll, BeforeAll}
import play.Application
import play.api.Play
import play.test.{Helpers, FakeApplication}

/**
 * @author Anton Oparin (antono@clemble.com)
 */
trait WithGlobalApplication extends BeforeAll with AfterAll {

  protected var app: Application = null

  /**
   * Override this method to setup the application to use.
   *
   * By default this will call the old {@link #provideFakeApplication() provideFakeApplication} method.
   *
   * @return The application to use
   */
  protected def provideApplication: Application = {
    return provideFakeApplication
  }

  /**
   * Old method - use the new {@link #provideApplication() provideApplication} method instead.
   *
   * Override this method to setup the fake application to use.
   *
   * @return The fake application to use
   */
  protected def provideFakeApplication: FakeApplication = {
    return Helpers.fakeApplication
  }

  override def beforeAll {
    app = provideApplication
    Helpers.start(app)
    Play.current
  }

  override def afterAll {
    if (app != null) {
      Helpers.stop(app)
      app = null
    }
  }

}
基本上,我采用了应用程序实现,并使其全球化

package com.equipx.spec.util

import org.specs2.specification.{AfterAll, BeforeAll}
import play.Application
import play.api.Play
import play.test.{Helpers, FakeApplication}

/**
 * @author Anton Oparin (antono@clemble.com)
 */
trait WithGlobalApplication extends BeforeAll with AfterAll {

  protected var app: Application = null

  /**
   * Override this method to setup the application to use.
   *
   * By default this will call the old {@link #provideFakeApplication() provideFakeApplication} method.
   *
   * @return The application to use
   */
  protected def provideApplication: Application = {
    return provideFakeApplication
  }

  /**
   * Old method - use the new {@link #provideApplication() provideApplication} method instead.
   *
   * Override this method to setup the fake application to use.
   *
   * @return The fake application to use
   */
  protected def provideFakeApplication: FakeApplication = {
    return Helpers.fakeApplication
  }

  override def beforeAll {
    app = provideApplication
    Helpers.start(app)
    Play.current
  }

  override def afterAll {
    if (app != null) {
      Helpers.stop(app)
      app = null
    }
  }

}