我正在使用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,则该模式不会为null

最佳答案

因此,我认为这与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时使用new关键字,如下所示:new FakeApplication() { override mode ... }导致模式通过null在GlobalSettings的onLoadConfig方法中。这感觉像是黑客,而不是解决方案,如果对此有足够的了解,谁可以发布一个解决方案,而不涉及复制完整的FakeApplication类并更改一行,我将不胜感激。

10-01 18:06