为了让scalatest中的数据库具有evolutions,我使用this SO question启发的默认PlaySpec
扩展名:
trait ResetDbSpec extends PlaySpec with BeforeAndAfterAll {
lazy val appBuilder = new GuiceApplicationBuilder()
lazy val injector = appBuilder.injector()
lazy val databaseApi = injector.instanceOf[DBApi]
override def beforeAll() = {
Evolutions.applyEvolutions(databaseApi.database("default"))
}
override def afterAll() = {
Evolutions.cleanupEvolutions(databaseApi.database("default"))
databaseApi.database("default").shutdown()
}
}
它在套件启动时应用数据库演变,并在套件结束时恢复它们。然后测试看起来像
class ProjectsSpec extends ResetDbSpec with OneAppPerSuite { ...
在添加了更多这样的测试之后,我遇到了一些问题,当我单独运行它们时,某些测试会成功,但是会出现此错误:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:数据源拒绝建立连接,来自服务器的消息:“连接太多”
从上面的代码中可以看出,我尝试添加行
databaseApi.database("default").shutdown()
afterAll()
中的可以减轻这种影响,但它没有效果。我试图不并行运行测试,但也没有效果。我在哪里打开数据库连接而不关闭它们,我应该在哪里调用shutdown()
?
N.B。我使用Play 2.5.10和Slick 3.1。
答案 0 :(得分:1)
虽然它没有回应连接泄漏的情况,但我终于成功解决了这个问题:
将 jdbc 添加到libraryDependencies,即使Play-Slick FAQ告诉您不要这样做:
# build.sbt
libraryDependencies += jdbc
重新启动sbt以考虑更改。在IntelliJ中,您也需要刷新项目。
禁用与play-slick冲突的 jdbc 模块(credit:this SO answer):
# application.conf
play.modules.disabled += "play.api.db.DBModule"
在同一个地方你应该已经配置了像
这样的东西slick {
dbs {
default {
driver = "slick.driver.MySQLDriver$"
db.driver = "com.mysql.jdbc.Driver"
db.url = "jdbc:mysql://localhost/test"
db.user = "sa"
db.password = ""
}
}
}
现在,您可以使用 jdbc 中的play.api.db.Databases
及其方法withDatabase
来运行演变。
import org.scalatest.BeforeAndAfterAll
import org.scalatestplus.play.PlaySpec
import play.api.db.{Database, Databases}
import play.api.db.evolutions.Evolutions
trait ResetDbSpec extends PlaySpec with BeforeAndAfterAll {
/**
* Here we use Databases.withDatabase to run evolutions without leaking connections.
* It slows down the tests considerably, though.
*/
private def withTestDatabase[T](block: Database => T) = {
Databases.withDatabase(
driver = "com.mysql.jdbc.Driver",
url = "jdbc:mysql://localhost/test",
name = "default",
config = Map(
"username" -> "sa",
"password" -> ""
)
)(block)
}
override def beforeAll() = {
withTestDatabase { database =>
Evolutions.applyEvolutions(database)
}
}
override def afterAll() = {
withTestDatabase { database =>
Evolutions.cleanupEvolutions(database)
}
}
}
最后,调用需要db重置的测试,如下所示:
class MySpec extends ResetDbSpec {...}
当然,在" application.test.conf"中都很难重复这个配置。在withDatabase()
中,加上它混合了两种不同的API,而不是性能。此外,它在每个套件之前和之后添加了这个,这很烦人:
[info] application - 为数据源创建池'默认'
[info] application - 关闭连接池。
如果有人有更好的建议,请改进这个答案!我已经挣扎了几个月。