我一直在使用官方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 { /* ... */ }
}
}
第一个似乎适用于第一个测试,然后在后面的测试中抱怨数据库连接问题。我猜这里有什么东西要关机或什么东西(不知道是什么)。
第二个根本不起作用,因为它抱怨没有正在运行的应用程序,我也不确定。
非常感谢任何帮助。谢谢!
答案 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实现,并使其成为全局。