播放2.3 FakeApplication模式未设置测试?

时间:2016-03-03 15:45:00

标签: scala testing scalatest

我正在使用play 2.3.8并在我的GlobalSettings中进行一些根据应用程序模式进行更改的配置。所以我有这样的事情:

object Global extends GlobalSettings {
    override def onLoadConfig(config: Configuration, path: java.io.File, classloader: ClassLoader, mode: Mode.Mode) = {
        println(mode)
        val customConfig = //Based on mode.*
        config ++ configuration ++ Configuration(ConfigFactory.parseMap(customConfig))
    }
}

然后我尝试编写测试以确保此行为有效:

class MyTest extends PlaySpec {

    val testApp = FakeApplication(
        additionalConfiguration = Map(
            //SomeSettings And Stuff
            "logger.application" -> "WARN",
            "logger.root" -> "WARN"
        )
    )

    val devApp = new FakeApplication(
        additionalConfiguration = Map(
            //SomeSettings And Stuff
            "logger.application" -> "WARN",
            "logger.root" -> "WARN"
        )
    ) {
        override val mode = Mode.Dev
    }

    val prodApp = new FakeApplication(
        additionalConfiguration = Map(
            //SomeSettings And Stuff
            "logger.application" -> "WARN",
            "logger.root" -> "WARN"
        )
    ) {
        override val mode = Mode.Prod
    }

    "ThisNonWorkingTestOfMine" must {

        "when running application in test mode have config.thing = false" in running(testApp) {
            assertResult(Mode.Test)(testApp.mode)
            assertResult(false)(testApp.configuration.getBoolean("config.thing").get)
        }

        "when running application in dev mode have config.thing = false" in running(devApp) {
            assertResult(Mode.Dev)(devApp.mode)
            assertResult(false)(devApp.configuration.getBoolean("config.thing").get)
        }

        "when running application in prod mode have config.thing = true" in running(prodApp) {
            assertResult(Mode.Prod)(prodApp.mode)
            assertResult(true)(prodApp.configuration.getBoolean("config.thing").get)
        }
    }

}

当我运行这些测试时,我从方便的println看到了一些奇怪的东西:

Test
null
null
[info] MyTest:
[info] ThisNonWorkingTestOfMine
[info] play - Starting application default Akka system.
[info] play - Shutdown application default Akka system.
[info] - must when running application in test mode have config.thing = false
[info] play - Application started (Dev)
[info] - must when running application in dev mode have config.thing = false
[info] play - Application started (Prod)
[info] - must when running application in prod mode have config.thing = true *** FAILED ***
[info]   Expected true, but got false (MyTest.scala:64)
[info] ScalaTest

如何在Play 2.3中正确设置FakeApplication的模式?我现在拥有它的方式是基于Mastering Play的页面,但显然使用onLoadConfig的方式似乎不是

修改: 我还尝试使用OneAppPerTest并在FakeApplication方法中创建newAppForTest,但它仍然表现得很奇怪,其中的null就像上面的方法一样。这真的很奇怪,因为如果我在制作"foo" -> "bar"时在additionalConfiguration地图中设置FakeApplication等随机属性,然后尝试在config.getString中读取Global对象,它被记录为None,即使我在测试本身app.configuration.getString显示bar。感觉这里存在某种类型的脱节。如果我使用FakeApplication.apply方法而不是new FakeApplication

,我就不会为该模式获取null

1 个答案:

答案 0 :(得分:0)

所以我认为这与the way that FakeApplication sets the mode to Mode.Test via override有关,因为如果我复制FakeApplication类并删除该行并创建我自己的类版本,让我设置模式我没有问题。换句话说,在我的测试包中,我声明了以下类:

package play.api.test

import play.api.mvc._
import play.api.libs.json.JsValue
import scala.concurrent.Future
import xml.NodeSeq
import play.core.Router
import scala.runtime.AbstractPartialFunction
import play.api.libs.Files.TemporaryFile
import play.api.{ Application, WithDefaultConfiguration, WithDefaultGlobal, WithDefaultPlugins }

case class FakeModeApplication(
    override val path: java.io.File = new java.io.File("."),
    override val classloader: ClassLoader = classOf[FakeModeApplication].getClassLoader,
    val additionalPlugins: Seq[String] = Nil,
    val withoutPlugins: Seq[String] = Nil,
    val additionalConfiguration: Map[String, _ <: Any] = Map.empty,
    val withGlobal: Option[play.api.GlobalSettings] = None,
    val withRoutes: PartialFunction[(String, String), Handler] = PartialFunction.empty,
    val mode: play.api.Mode.Value
) extends {
    override val sources = None
} with Application with WithDefaultConfiguration with WithDefaultGlobal with WithDefaultPlugins {
    override def pluginClasses = {
        additionalPlugins ++ super.pluginClasses.diff(withoutPlugins)
    }

    override def configuration = {
        super.configuration ++ play.api.Configuration.from(additionalConfiguration)
    }

    override lazy val global = withGlobal.getOrElse(super.global)

    override lazy val routes: Option[Router.Routes] = {
        val parentRoutes = loadRoutes
        Some(new Router.Routes() {
            def documentation = parentRoutes.map(_.documentation).getOrElse(Nil)
            // Use withRoutes first, then delegate to the parentRoutes if no route is defined
            val routes = new AbstractPartialFunction[RequestHeader, Handler] {
                override def applyOrElse[A <: RequestHeader, B >: Handler](rh: A, default: A => B) =
                    withRoutes.applyOrElse((rh.method, rh.path), (_: (String, String)) => default(rh))
                def isDefinedAt(rh: RequestHeader) = withRoutes.isDefinedAt((rh.method, rh.path))
            } orElse new AbstractPartialFunction[RequestHeader, Handler] {
                override def applyOrElse[A <: RequestHeader, B >: Handler](rh: A, default: A => B) =
                    parentRoutes.map(_.routes.applyOrElse(rh, default)).getOrElse(default(rh))
                def isDefinedAt(x: RequestHeader) = parentRoutes.map(_.routes.isDefinedAt(x)).getOrElse(false)
            }
            def setPrefix(prefix: String) {
                parentRoutes.foreach(_.setPrefix(prefix))
            }
            def prefix = parentRoutes.map(_.prefix).getOrElse("")
        })
    }
}

然后在我的测试中我可以像这样使用它:

val devApp = new FakeModeApplication(
    additionalConfiguration = Map(
        //SomeSettings And Stuff
        "logger.application" -> "WARN",
        "logger.root" -> "WARN"
    ), mode = Mode.Dev
)

然后模式值通过我设置的而不是null来实现。

我将此作为答案发布,因为它确实解决了我所面临的问题,但在制作FakeApplication时,我并不理解为什么新关键字:{ {1}}导致模式在GlobalSettings上的new FakeApplication() { override mode ... }方法中为null。这感觉就像是一个黑客而不是解决方案,如果有足够知识的人可以发布一个不涉及复制完整的FakeApplication类并更改一行的解决方案,我会很感激。