我们正在使用
在子项目“服务”中,我们(想要)使用Guice在用于产品的 MySql 和用于单元测试的 H2 之间切换。 这在过去是可行的,但现在我们也使用进化来产生问题。
我们的 application.conf 文件包含一些进行演变的行:
db.default = {
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/dev"
url=${?rds.url}
username="dev-user"
username= ${?rds.user}
password="<secret>"
password=${?rds.password}
}
一个示例测试类如下
class HomeControllerTest extends PlaySpec with GuiceOneAppPerTest with BeforeAndAfterAll {
val application: play.api.Application = new GuiceApplicationBuilder()
.in(Mode.Test)
.overrides(
bind[DbComponent].to(classOf[H2DbComponent])
).build()
// the same for:
override def fakeApplication(): Application = new GuiceApplicationBuilder()...
// the same for:
implicit override lazy val app: play.api.Application = new GuiceApplicationBuilder()...
问题: 运行使用Guice的测试类时,Evolution尝试访问“默认” MySql数据库。这不是故意的,并且在Jenkins上运行时将使测试失败。 当'db.default = {...}'行被注释掉时,测试运行正常。
为解决此问题,我们还有一个替代的 conf / application.test.conf 文件,其中包含用于覆盖“默认”数据库设置的行:
db.default = {
driver = "org.h2.Driver"
url = "jdbc:h2:mem:h2test;MODE=MySql;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS dev_db"
}
并在 service / build.sbt 行中添加
javaOptions in Test += "-Dconfig.resource=application.test.conf"
事实证明,Guice不使用备用配置文件 application.test.conf 。可以通过分析 play.api.db.DBApiProvider :: get 中的“ configuration”的值来验证。
为了克服这个问题,测试类现在看起来像
class HomeControllerTest extends PlaySpec with GuiceOneAppPerTest with BeforeAndAfterAll {
val configuration: Configuration = Configuration.reference ++ Configuration(ConfigFactory.parseResources("application.test.conf").resolve)
val application: play.api.Application = new GuiceApplicationBuilder()
.in(Mode.Test)
.loadConfig(configuration)
.overrides(
bind[DbComponent].to(classOf[H2DbComponent])
).build()
这会产生错误:
Exception encountered when invoking run on a nested suite - Guice configuration errors:
1) No implementation for play.api.Application was bound.
while locating play.api.Application
1 error
com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for play.api.Application was bound.
while locating play.api.Application
1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1045)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054)
at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:409)
at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:404)
at play.api.inject.ContextClassLoaderInjector.$anonfun$instanceOf$2(Injector.scala:117)
at play.api.inject.ContextClassLoaderInjector.withContext(Injector.scala:126)
at play.api.inject.ContextClassLoaderInjector.instanceOf(Injector.scala:117)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
at controllers.HomeControllerTest.fakeApplication(HomeControllerTest.scala:36)
at org.scalatestplus.play.BaseOneAppPerSuite.app(BaseOneAppPerSuite.scala:29)
at org.scalatestplus.play.BaseOneAppPerSuite.app$(BaseOneAppPerSuite.scala:29)
at controllers.HomeControllerTest.app$lzycompute(HomeControllerTest.scala:22)
at controllers.HomeControllerTest.app(HomeControllerTest.scala:22)
at org.scalatestplus.play.BaseOneAppPerSuite.run(BaseOneAppPerSuite.scala:42)
at org.scalatestplus.play.BaseOneAppPerSuite.run$(BaseOneAppPerSuite.scala:41)
at controllers.HomeControllerTest.org$scalatest$BeforeAndAfterAll$$super$run(HomeControllerTest.scala:22)
at org.scalatest.BeforeAndAfterAll.liftedTree1$1(BeforeAndAfterAll.scala:213)
at org.scalatest.BeforeAndAfterAll.run(BeforeAndAfterAll.scala:210)
at org.scalatest.BeforeAndAfterAll.run$(BeforeAndAfterAll.scala:208)
at controllers.HomeControllerTest.run(HomeControllerTest.scala:22)
at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:45)
at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13(Runner.scala:1346)
at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13$adapted(Runner.scala:1340)
at scala.collection.immutable.List.foreach(List.scala:389)
at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1340)
at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24(Runner.scala:1031)
at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24$adapted(Runner.scala:1010)
at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1506)
at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1010)
at org.scalatest.tools.Runner$.run(Runner.scala:850)
at org.scalatest.tools.Runner.run(Runner.scala)
at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:131)
at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)
为处理内存中测试数据库的演化而提出的可行解决方案是什么?
非常感谢