使用“in new WithApplication”时如何在specs2中进行设置/拆卸

时间:2014-03-07 00:34:08

标签: scala playframework specs2

我正在使用带有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

2 个答案:

答案 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的类,它接受两个匿名函数setupteardown,它们都返回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")
}