在 play 2.4 和 Slick 3 中为单元测试设置内存数据库时遇到问题
Having Trouble setting up in memory db for unit tests in play 2.4 an Slick 3
我正在尝试在内存中设置一个 h2 数据库,然后使用 Slicks 功能创建必要的表,以用于我的 play specs2 测试。我已经创建了一个抽象 class 覆盖 WithApplication 然后覆盖 around 方法但是当 createTables 函数尝试 运行 预测试时我得到一个错误。我怀疑我没有正确传递数据库连接/配置,但我得到的错误不是很有帮助。我正在通过包装播放 Databases.withInMemory 函数
创建数据库
这是我的数据库助手对象
package testHelpers
import models.VisitorImages._
import models.VisitorRegistrations._
import models.VisitorSignatures._
import models.VisitorStatuses._
import models.Visitors._
import org.specs2.execute.{Result, AsResult}
import play.api.test.WithApplication
import play.api.{Logger, Application, Play}
import play.api.db.slick.DatabaseConfigProvider
import play.api.db.{Databases, Database}
import slick.backend.DatabaseConfig
import slick.profile.{BasicProfile, RelationalProfile}
import scala.concurrent.Await
import scala.concurrent.duration.Duration
object TestDatabase {
class testDbProvider extends DatabaseConfigProvider {
def get[P <: BasicProfile]: DatabaseConfig[P] = {
DatabaseConfigProvider.get("default")(Play.current)
}
}
def startTestDb[T](block: Database => T) = {
Databases.withInMemory(
name = "testDB",
urlOptions = Map(
"MODE" -> "MSSQLServer"
),
config = Map(
"logStatements" -> true
)
)(block)
}
abstract class WithTestDb extends WithApplication((TestApplication.application)) {
val profile = slick.driver.H2Driver
import profile.api._
override def around[T: AsResult](t: => T): Result = super.around {
setupData()
t
}
val allTables = (VisitorSignatures.schema ++ VisitorImages.schema ++ Visitors.schema ++ VisitorStatuses.schema ++ VisitorRegistrations.schema
).create
/** Create all tables in database */
def createTables = {
Logger.info(s"yadda yadda yadda")
val db = new testDbProvider().get.db
Await.result(db.run(Visitors.schema.create), Duration.Inf)
Logger.info(s"variable user is blah blah")
}
/** Delete all tables in database */
def drop = {
// allTables.drop
}
def setupData() {
// setup data
createTables
}
}
}
这是我尝试使用它的方式
package unit.models
import models.VisitorRegistrations._
import play.api.{Play, db}
import play.api.db.slick.DatabaseConfigProvider
import play.api.test.{WithApplication, PlaySpecification}
import play.db.NamedDatabase
import providers.VisitorRegistrationProvider
import repositories.VisitorRegistrationRepository
import slick.driver.JdbcProfile
import slick.lifted.TableQuery
import testHelpers.TestDatabase.WithTestDb
import testHelpers.{Inject, TestApplication, TestDatabase}
import scala.concurrent.Await
import scala.concurrent.duration.Duration
class VisitorRegistrationsSpec extends PlaySpecification with Inject {
val vrp = inject[VisitorRegistrationProvider]
val db = vrp.dbConfig.db
import vrp.dbConfig.driver.api._
TestDatabase.startTestDb { database =>
"VisitorResgistrations" should {
"save a vr" in new WithTestDb {
val res = Await.result(db.run(VisitorRegistrations.result), Duration.Inf)
res must equalTo(1)
}
}
}
}
这是我得到的错误
[info] VisitorResgistrations should
[error] ! save a vr
[error] null (Database.scala:61)
[error] testHelpers.TestDatabase$WithTestDb.createTables(Database.scala:61)
[error] testHelpers.TestDatabase$WithTestDb.setupData(Database.scala:72)
[error] testHelpers.TestDatabase$WithTestDb$$anonfun$around.apply(Database.scala:50)
[error] play.api.test.WithApplication$$anonfun$around.apply(Specs.scala:39)
[error] play.api.test.WithApplication$$anonfun$around.apply(Specs.scala:39)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:42)
[error] play.api.test.Helpers$.running(Helpers.scala:363)
[error] play.api.test.WithApplication.around(Specs.scala:39)
[error] testHelpers.TestDatabase$WithTestDb.around(Database.scala:49)
[error] play.api.test.WithApplication.delayedInit(Specs.scala:36)
[error] testHelpers.TestDatabase$WithTestDb.<init>(Database.scala:45)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$$anonfun$apply$$anonfun$apply$$anon.<init>(VisitorRegistrationsSpec.scala:30)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$$anonfun$apply$$anonfun$apply.apply(VisitorRegistrationsSpec.scala:30)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$$anonfun$apply$$anonfun$apply.apply(VisitorRegistrationsSpec.scala:30)
Off-hand,看来你的初始化顺序有问题。尝试将 class-level val
更改为 lazy val
或 def
.
我正在尝试在内存中设置一个 h2 数据库,然后使用 Slicks 功能创建必要的表,以用于我的 play specs2 测试。我已经创建了一个抽象 class 覆盖 WithApplication 然后覆盖 around 方法但是当 createTables 函数尝试 运行 预测试时我得到一个错误。我怀疑我没有正确传递数据库连接/配置,但我得到的错误不是很有帮助。我正在通过包装播放 Databases.withInMemory 函数
创建数据库这是我的数据库助手对象
package testHelpers
import models.VisitorImages._
import models.VisitorRegistrations._
import models.VisitorSignatures._
import models.VisitorStatuses._
import models.Visitors._
import org.specs2.execute.{Result, AsResult}
import play.api.test.WithApplication
import play.api.{Logger, Application, Play}
import play.api.db.slick.DatabaseConfigProvider
import play.api.db.{Databases, Database}
import slick.backend.DatabaseConfig
import slick.profile.{BasicProfile, RelationalProfile}
import scala.concurrent.Await
import scala.concurrent.duration.Duration
object TestDatabase {
class testDbProvider extends DatabaseConfigProvider {
def get[P <: BasicProfile]: DatabaseConfig[P] = {
DatabaseConfigProvider.get("default")(Play.current)
}
}
def startTestDb[T](block: Database => T) = {
Databases.withInMemory(
name = "testDB",
urlOptions = Map(
"MODE" -> "MSSQLServer"
),
config = Map(
"logStatements" -> true
)
)(block)
}
abstract class WithTestDb extends WithApplication((TestApplication.application)) {
val profile = slick.driver.H2Driver
import profile.api._
override def around[T: AsResult](t: => T): Result = super.around {
setupData()
t
}
val allTables = (VisitorSignatures.schema ++ VisitorImages.schema ++ Visitors.schema ++ VisitorStatuses.schema ++ VisitorRegistrations.schema
).create
/** Create all tables in database */
def createTables = {
Logger.info(s"yadda yadda yadda")
val db = new testDbProvider().get.db
Await.result(db.run(Visitors.schema.create), Duration.Inf)
Logger.info(s"variable user is blah blah")
}
/** Delete all tables in database */
def drop = {
// allTables.drop
}
def setupData() {
// setup data
createTables
}
}
}
这是我尝试使用它的方式
package unit.models
import models.VisitorRegistrations._
import play.api.{Play, db}
import play.api.db.slick.DatabaseConfigProvider
import play.api.test.{WithApplication, PlaySpecification}
import play.db.NamedDatabase
import providers.VisitorRegistrationProvider
import repositories.VisitorRegistrationRepository
import slick.driver.JdbcProfile
import slick.lifted.TableQuery
import testHelpers.TestDatabase.WithTestDb
import testHelpers.{Inject, TestApplication, TestDatabase}
import scala.concurrent.Await
import scala.concurrent.duration.Duration
class VisitorRegistrationsSpec extends PlaySpecification with Inject {
val vrp = inject[VisitorRegistrationProvider]
val db = vrp.dbConfig.db
import vrp.dbConfig.driver.api._
TestDatabase.startTestDb { database =>
"VisitorResgistrations" should {
"save a vr" in new WithTestDb {
val res = Await.result(db.run(VisitorRegistrations.result), Duration.Inf)
res must equalTo(1)
}
}
}
}
这是我得到的错误
[info] VisitorResgistrations should
[error] ! save a vr
[error] null (Database.scala:61)
[error] testHelpers.TestDatabase$WithTestDb.createTables(Database.scala:61)
[error] testHelpers.TestDatabase$WithTestDb.setupData(Database.scala:72)
[error] testHelpers.TestDatabase$WithTestDb$$anonfun$around.apply(Database.scala:50)
[error] play.api.test.WithApplication$$anonfun$around.apply(Specs.scala:39)
[error] play.api.test.WithApplication$$anonfun$around.apply(Specs.scala:39)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:42)
[error] play.api.test.Helpers$.running(Helpers.scala:363)
[error] play.api.test.WithApplication.around(Specs.scala:39)
[error] testHelpers.TestDatabase$WithTestDb.around(Database.scala:49)
[error] play.api.test.WithApplication.delayedInit(Specs.scala:36)
[error] testHelpers.TestDatabase$WithTestDb.<init>(Database.scala:45)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$$anonfun$apply$$anonfun$apply$$anon.<init>(VisitorRegistrationsSpec.scala:30)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$$anonfun$apply$$anonfun$apply.apply(VisitorRegistrationsSpec.scala:30)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$$anonfun$apply$$anonfun$apply.apply(VisitorRegistrationsSpec.scala:30)
Off-hand,看来你的初始化顺序有问题。尝试将 class-level val
更改为 lazy val
或 def
.