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

时间:2013-11-26 22:03:31

标签: scala playframework specs2

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

"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) { /* ... */ }
}

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

第一个似乎适用于第一个测试,然后在后面的测试中抱怨数据库连接问题。我猜这里有什么东西要关机或什么东西(不知道是什么)。

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

非常感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:4)

嗯,这取决于你想要测试的内容。如果您只是单元测试没有外部依赖关系或依赖关系的代码,您可以模拟或存根(并且以允许这种方式构建代码是一个好主意),那么您不需要使用WithApplication。这可能是最好的方法。

您提供的第一个解决方案不起作用,因为应用程序只能使用一次。它是WithApplication启动和停止你的应用程序,所以即使它确实有效,你也不会获得任何性能上的好处。

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

因此,如果您无法独立于应用程序的其余部分测试代码,那么您需要拥有一个正在运行的应用程序,您无需做任何事情,这是集成测试的现实。并且您可能希望它在每次测试之间启动和关闭,否则您的测试不会彼此孤立地运行。

答案 1 :(得分:3)

它已经过时了,但我会给出答案。既然我遇到同样的问题,也有类似的想法。有AfterAll&之前在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
    }
  }

}

基本上我采用了WithApplication实现,并使其成为全局。

相关问题