gpt4 book ai didi

从application.conf中获取数据源时,Scala Play没有启动应用程序

转载 作者:行者123 更新时间:2023-12-04 13:59:39 29 4
gpt4 key购买 nike

我试图从我的 application.conf 文件中读取数据源,但是每次我运行我的服务器或尝试运行测试用例时,我都会收到一条错误消息,指出没有启动应用程序。

这是我正在尝试做的一个例子:

试图从我的 application.conf 读取属性的单元测试

class DbConfigWebUnitTest extends PlaySpec with OneAppPerSuite {

implicit override lazy val app: FakeApplication = FakeApplication(
additionalConfiguration = Map("db.test.url" -> "jdbc:postgresql://localhost:5432/suredbitswebtest",
"db.test.user" -> "postgres", "db.test.password" -> "postgres", "db.test.driver" -> "org.postgresql.Driver"))
val dbManagementWeb = new DbManagementWeb with DbConfigWeb with DbTestQualifier
"DbConfigWebTest" must {
"have the same username as what is defined in application.conf" in {
dbManagementWeb.username must be("postgres")
}
}
}

这是我的 DbConfigWeb
import play.api.Play.current    
trait DbConfigWeb extends DbConfig { qualifier: DbQualifier =>

val url: String = current.configuration.getString(qualifier + ".url").get
val username: String = current.configuration.getString(qualifier + ".user").get
val password: String = current.configuration.getString(qualifier + ".password").get
val driver: String = current.configuration.getString(qualifier + ".driver").get
override def database: DatabaseDef = JdbcBackend.Database.forURL(url, username, password, null, driver)
override implicit val session = database createSession
}

trait DbQualifier {
val qualifier: String
}

trait DbProductionQualifier extends DbQualifier {
override val qualifier = "db.production"
}

trait DbTestQualifier extends DbQualifier {
override val qualifier = "db.test"
}

最后这是我的堆栈跟踪:
[suredbits-web] $ last test:test
[debug] Forking tests - parallelism = false
[debug] Create a single-thread test executor
[debug] Runner for sbt.FrameworkWrapper produced 0 initial tasks for 0 tests.
[debug] Runner for org.scalatest.tools.Framework produced 2 initial tasks for 2 tests.
[debug] Running TaskDef(com.suredbits.web.db.DbConfigWebUnitTest, sbt.ForkMain$SubclassFingerscan@48687c55, false, [SuiteSelector])
[error] Uncaught exception when running com.suredbits.web.db.DbConfigWebUnitTest: java.lang.RuntimeException: There is no started application
sbt.ForkMain$ForkError: There is no started application
at scala.sys.package$.error(package.scala:27)
at play.api.Play$$anonfun$current$1.apply(Play.scala:71)
at play.api.Play$$anonfun$current$1.apply(Play.scala:71)
at scala.Option.getOrElse(Option.scala:120)
at play.api.Play$.current(Play.scala:71)
at com.suredbits.web.db.DbConfigWeb$class.$init$(DbConfigWebProduction.scala:14)
at com.suredbits.web.db.DbConfigWebUnitTest$$anon$1.<init>(DbConfigWebUnitTest.scala:14)
at com.suredbits.web.db.DbConfigWebUnitTest.<init>(DbConfigWebUnitTest.scala:14)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:379)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:641)
at sbt.ForkMain$Run$2.call(ForkMain.java:294)
at sbt.ForkMain$Run$2.call(ForkMain.java:284)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)

最佳答案

我认为关键问题是val Scala 特征中的 s 在构建时初始化,这是在测试 Play 应用程序启动之前(大概它的生命周期与每个规范示例相关联。)您有几个解决方法:

  • 让一切尽在 DbConfigWeb def或者可能是 lazy val
  • DbConfigWeb摘要 play.api.Application从中提取配置值的字段(而不是使用 current )并将其显式(假应用程序)传递给任何 DbManagementWeb作为构造函数参数

  • 这是一个简化版本,使用第一种方法(对我有用):
    import play.api.Play.current

    trait DbConfig

    trait DbConfigWeb extends DbConfig {
    self: DbQualifier =>

    // Using defs instead of vals
    def url: String = current.configuration.getString(qualifier + ".url").get
    def username: String = current.configuration.getString(qualifier + ".user").get
    def password: String = current.configuration.getString(qualifier + ".password").get
    def driver: String = current.configuration.getString(qualifier + ".driver").get
    }

    trait DbQualifier {
    val qualifier: String
    }

    trait DbTestQualifier extends DbQualifier {
    override val qualifier = "db.test"
    }

    和规范:
    import controllers.{DbConfigWeb, DbTestQualifier}
    import org.scalatestplus.play.{OneAppPerSuite, PlaySpec}
    import play.api.test.FakeApplication

    class DbConfigTest extends PlaySpec with OneAppPerSuite {
    implicit override lazy val app: FakeApplication = FakeApplication(
    additionalConfiguration = Map("db.test.url" -> "jdbc:h2:mem:play",
    "db.test.user" -> "sa", "db.test.password" -> "", "db.test.driver" -> "org.h2.Driver"))
    val dbManagementWeb = new DbConfigWeb with DbTestQualifier
    "DbConfigWebTest" must {
    "have the same username as what is defined in application.conf" in {
    dbManagementWeb.username must be("sa")
    }
    }
    }

    我个人更喜欢第二种方法,它保持应用程序状态明确传递而不是依赖于 play.api.Play.current , 你 不能 依赖总是被启动。

    您在评论中提到 lazy val s 不适合您,但我只能推测某些调用链正在强制初始化:再次检查是否不是这种情况。

    还要注意 val 的初始化顺序s 可能很复杂,虽然有些人可能不同意,但坚持 def 是一个非常安全的赌注。 s 作为特征成员,除非您确定这是一些昂贵的操作(在这种情况下,惰性 val 可能是一种选择。)

    关于从application.conf中获取数据源时,Scala Play没有启动应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28387203/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com