Scala在从application.conf获取数据源时没有启动应用程序
发布时间:2020-12-16 18:41:33 所属栏目:安全 来源:网络整理
导读:我试图从我的application.conf文件中读取数据源,但每次运行我的服务器,或者尝试运行测试用例时,我都会收到错误消息,说明没有应用程序启动. 这是我想要做的一个例子: 尝试从我的application.conf读取属性的单元测试 class DbConfigWebUnitTest extends PlayS
我试图从我的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) 解决方法
我认为关键问题是Scala特征中的val是在构建时初始化的,这是在测试Play应用程序启动之前(可能是它的生命周期与每个规范示例相关联.)您有几个解决方法:
>让DbConfigWeb中的所有内容成为def或者懒惰的val 这是一个简化版本,使用第一种方法(适用于我): 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,你不能依赖它总是被启动. 你在评论中提到懒惰的val不适合你,但我只能猜测某些调用链是强制初始化:再次检查是不是这种情况. 另请注意,val的初始化顺序可能很复杂,虽然有些人可能不同意,但坚持将def作为特征成员是非常安全的选择,除非你确定它是一些昂贵的操作(在这种情况下,懒惰的val可能是一个选项) .) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |