我正在使用带有Scala 2.10.2(运行Java 1.7.0_51)构建的play 2.2.1的Specs2。我一直在阅读有关如何使用Specs2进行设置/拆卸的内容。我看过使用“After”特征的例子如下:
class Specs2Play extends org.specs2.mutable.Specification {
"this is the first example" in new SetupAndTeardownPasswordAccount {
println("testing")
}
}
trait SetupAndTeardownPasswordAccount extends org.specs2.mutable.After {
println("setup")
def after = println("teardown ")
}
除了我的所有测试都使用“在新的WithApplication中”之外,这个工作正常。看来我需要的是一个既是“WithApplication”又是“After”的对象。下面不编译,但基本上是我想要的:
trait SetupAndTeardownPasswordAccount extends org.specs2.mutable.After with WithApplication
所以,我的问题是,如何在已经使用“WithApplication”的测试中添加setup / teardown?我主要担心的是我们所有的测试都使用了这样的伪路由(所以他们需要With Application)。
val aFakeRequest = FakeRequest(method, url).withHeaders(headers).withBody(jsonBody)
val Some(result) = play.api.test.Helpers.route(aFakeRequest)
result
答案 0 :(得分:6)
这是WithApplication
的代码:
abstract class WithApplication(val app: FakeApplication = FakeApplication()) extends Around with Scope {
implicit def implicitApp = app
override def around[T: AsResult](t: => T): Result = {
Helpers.running(app)(AsResult.effectively(t))
}
}
实际上很容易修改它以满足您的需求而不会产生许多其他特征。这里缺少的是匿名函数t
,您可以在测试中提供实现(使用WithApplication
)。如果必要的话,让WithApplication
更加健壮以便能够在测试之前和之后执行任意代码块会更好。
一种方法可能是创建一个类似于WithApplication
的类,它接受两个匿名函数setup
和teardown
,它们都返回Unit
。我真正需要做的就是修改AsResult.effectively(t)
内发生的事情。为了简单起见,我将从参数列表中删除app
参数,并始终使用FakeApplication
。您似乎没有提供不同的配置,并且可以随时添加它。
abstract class WithEnv(setup: => Unit, teardown: => Unit) extends Around with Scope {
implicit def implicitApp = app
override def around[T: AsResult](t: => T): Result = {
Helpers.running(app)(AsResult.effectively{
setup
try {
t
} finally {
teardown
}
})
}
}
我不是简单地调用匿名函数t
,而是先调用setup
,然后调用t
,然后调用teardown
。 try / finally块非常重要,因为specs2中的测试失败会抛出异常,我们希望确保teardown
无论结果如何都会被执行。
现在,您可以使用函数轻松设置测试环境。
import java.nio.files.{Files, Paths}
def createFolder: Unit = Files.createDirectories(Paths.get("temp/test"))
def deleteFolder: Unit = Files.delete("temp/test")
"check if a file exists" in new WithEnv(createFolder, deleteFolder) {
Files.exists(Paths.get("temp/test")) must beTrue
}
(这可能无法编译,但你明白了。)
答案 1 :(得分:2)
如果您的after
方法不需要WithApplication
特征中的任何内容,您可以在规范中混合AfterExample
特征并定义整个规范的after
行为:
import org.specs2.specification._
class Specs2Play extends org.specs2.mutable.Specification with AfterExample {
"this is the first example" in new SetupAndTeardownPasswordAccount {
pending("testing")
}
trait SetupAndTeardownPasswordAccount extends WithApplication
def after = println("cleanup")
}