简体   繁体   English

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

[英]How to do setup/teardown in specs2 when using “in new WithApplication”

I am using Specs2 with play 2.2.1 built with Scala 2.10.2 (running Java 1.7.0_51). 我正在使用带有Scala 2.10.2(运行Java 1.7.0_51)构建的play 2.2.1的Specs2。 I have been reading about how to do setup/teardown with Specs2. 我一直在阅读有关如何使用Specs2进行设置/拆卸的内容。 I have seen examples using the "After" trait as follows: 我看过使用“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 ")
}

This works fine, except that all of my tests are using "in new WithApplication". 这很好,除了我的所有测试都使用“在新的WithApplication中”。 It seems what I need is to have an object which is both a "WithApplication" and an "After". 看来我需要的是一个既是“WithApplication”又是“After”的对象。 Below does not compile, but is essentially what I want: 下面不编译,但基本上是我想要的:

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

So, my question is, how do I add setup/teardown to my tests which are already using "in WithApplication"? 所以,我的问题是,如何在已经使用“InApplication”的测试中添加setup / teardown? My primary concern is that all of our tests make use of fake routing like this (so they need the With Application). 我主要担心的是我们所有的测试都使用了这样的伪路由(所以他们需要With Application)。

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

This is the code for WithApplication : 这是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))
  }
}

It's actually quite easy to modify this to suit your needs without creating a bunch of other traits. 实际上很容易修改它以满足您的需求而不会产生许多其他特征。 The missing piece here is the anonymous function t , which you provide the implementation for in your tests (using WithApplication ). 这里缺少的部分是匿名函数t ,您可以在测试中提供实现(使用WithApplication )。 It would be nice to make WithApplication a little more robust to be able to execute arbitrary blocks of code before and after the tests, if necessary. 如果有必要,最好使WithApplication更加健壮,以便能够在测试之前和之后执行任意代码块。

One approach could be to create a similar class to WithApplication that accepts two anonymous functions setup and teardown that both return Unit . 一种方法可能是创建一个类似于WithApplication类,它接受两个匿名函数setupteardown ,它们都返回Unit All I really need to do is modify what's happening inside AsResult.effectively(t) . 我真正需要做的就是修改AsResult.effectively(t)发生的事情。 To keep this simple, I'm going to remove the app parameter from the parameter list, and use FakeApplication always. 为了简单FakeApplication ,我将从参数列表中删除app参数,并始终使用FakeApplication You don't seem to be providing a different configuration, and it can always be added back. 您似乎没有提供不同的配置,它总是可以添加回来。

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

Instead of simply calling the anonymous function t , I first call setup , then t , then teardown . 我不是简单地调用匿名函数t ,而是首先调用setup ,然后是t ,然后是teardown The try/finally block is important because failed tests in specs2 throw exceptions, and we want to be sure that teardown will be executed no matter what the outcome. try / finally块很重要,因为specs2中的测试失败会引发异常,我们希望确保无论结果如何都会执行teardown

Now you can easily setup test environments using functions. 现在,您可以使用功能轻松设置测试环境。

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
}

(This might not compile, but you get the idea.) (这可能无法编译,但你明白了。)

If your after method doesn't need anything from the WithApplication trait you can mix in your specification the AfterExample trait and define the after behaviour for the whole spec: 如果你的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")
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM