2014-03-07 22 views
3

我在使用Scala 2.10.2(运行Java 1.7.0_51)构建的play 2.2.1中使用Specs2。我一直在阅读如何使用Specs2进行安装/拆卸。我看过使用“After”特征的例子,如下所示:如何在使用“in new WithApplication”时在specs2中进行setup/teardown

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 ") 
} 

这很好,除了我所有的测试都使用“in new WithApplication”。看来我需要的是一个既有“WithApplication”又有“After”的对象。下面无法编译,但本质上是什么,我想:

trait SetupAndTeardownPasswordAccount extends org.specs2.mutable.After with WithApplication 

所以,我的问题是,如何做我安装/拆卸添加到其已经“在WithApplication”用我的测试?我主要关心的是,我们所有的测试都使用这样的假路由(所以他们需要With Application)。

val aFakeRequest = FakeRequest(method, url).withHeaders(headers).withBody(jsonBody) 
val Some(result) = play.api.test.Helpers.route(aFakeRequest) 
result 

回答

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 
} 

(这可能无法编译,但你的想法。)

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") 
} 
+0

我喜欢你的建议,但它不完全工作。问题是在设置中我们有一个保存数据的上下文。拆解需要访问该环境。我已经生成了用户标识等,它们只存储在安装上下文中。你可以改进它,以便设置/拆卸上下文相同吗? – thebiggestlebowski

+1

您可以使用'context'变量并将规范运行为'isolated'(以便每个示例在它自己的规范类中作为'sequential'在运行时执行(这样每个示例就不会彼此踩在一起) 。否则,您需要使用其他解决方案来解决您的问题(通过@LimbSoup) – Eric

相关问题