我正在处理使用Play 2.5.10和Slick 3.1.1的this github project(可以通过运行sbt test
来重现该问题,但可以also be checked directly in travis CI)。我使用Postgres数据库配置default
进行开发和生产。然后我在名为test
的内存数据库中使用H2进行测试。 default
数据库在conf/application.conf
中配置,而test
数据库在conf/application.test.conf
中配置。
问题是,对于测试,我使用名称test
初始化数据库,但使用GuiceApplicationBuilder
构建的应用程序仍在使用default
。
此行在我的build.sbt
中以获取测试配置:
javaOptions in Test += "-Dconfig.file=conf/application.test.conf"
这是该文件的内容:
include "application.conf"
slick.dbs {
test {
driver="slick.driver.H2Driver$"
db.driver="org.h2.Driver"
db.url="jdbc:h2:mem:test;MODE=PostgreSQL"
db.username="sa"
db.password=""
}
}
我的DaoFunSpec
基类看起来像这样:
package dao
import org.scalatest.{BeforeAndAfterAll, FunSpec}
import org.scalatestplus.play.OneAppPerSuite
import play.api.Application
import play.api.db.evolutions.Evolutions
import play.api.db.DBApi
abstract class DaoFunSpec extends FunSpec with OneAppPerSuite with BeforeAndAfterAll {
lazy implicit val db = app.injector.instanceOf[DBApi].database("test")
override def beforeAll() {
Evolutions.applyEvolutions(db)
}
override def afterAll() {
Evolutions.cleanupEvolutions(db)
}
def userDao(implicit app: Application) = {
Application.instanceCache[UserDao].apply(app)
}
}
注意第app.injector.instanceOf[DBApi].database("test")
行,但Play仍尝试连接default
数据库。
答案 0 :(得分:3)
好的,你的问题有点不同(或者可能有点意外)。这是引起你头痛的因素:
dbApi.databases().foreach(runEvolutions)
它位于:ApplicationEvolutions.scala:42
这可能是不言自明的:)
问题仍然存在。实际上,您的测试环境中有两个数据库(default
和test
)。现在这会导致一些问题 - 您在上面看到了其中一个问题(每个问题都在尝试进化)。另一个是如果你想使用不同名称的db,你不能只注入类似的东西:
class UserDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
相反,你需要使用(AFAIR):
class UserDao @Inject()(@NamedDatabase("test") protected val dbConfigProvider: DatabaseConfigProvider)
但在这种情况下,你的测试变得更加复杂。
如果出现以下情况会更简单:
1)您可以将常用配置提取到common.conf
2)您可以将application.conf
更改为以下内容:
include "common.conf"
slick.dbs {
default {
driver="slick.driver.PostgresDriver$"
db.driver="org.postgresql.Driver"
db.url="jdbc:postgresql://localhost:5432/exampledb?searchpath=public"
db.user="postgres"
db.password="postgres"
}
}
3)您可以将application.test.conf
更改为以下内容:
include "common.conf"
slick.dbs {
default {
driver="slick.driver.H2Driver$"
db.driver="org.h2.Driver"
db.url="jdbc:h2:mem:test;MODE=PostgreSQL"
db.username="sa"
db.password=""
}
}
现在唯一的事情就是你应该有一套演变(default
),这实际上并没有那么糟糕,因为它会确保你的测试数据库与你的生产数据库同步(至少在术语上)结构)。
上述并不是唯一的解决方案。你仍然可以有两个不同命名的db配置;你需要在这种情况下在你的Guilce module
中进行某种重新映射(然后你会有一个模块用于prod,一个用于测试 - 它们可以相互继承并且只覆盖某些东西 - 例如附加{{ 1}} db代替默认值1)。这基本上是一种品味问题。