【问题标题】:Having Trouble setting up in memory db for unit tests in play 2.4 an Slick 3在播放 2.4 和 Slick 3 中无法在内存数据库中设置单元测试
【发布时间】:2016-01-18 15:54:20
【问题描述】:

我正在尝试设置一个 in Memory h2 db,然后使用 Slicks 功能创建必要的表,以用于我的 play specs2 测试。我创建了一个覆盖 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$1.apply(Database.scala:50)
[error] play.api.test.WithApplication$$anonfun$around$2.apply(Specs.scala:39)
[error] play.api.test.WithApplication$$anonfun$around$2.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$1$$anonfun$apply$2$$anonfun$apply$3$$anon$1.<init>(VisitorRegistrationsSpec.scala:30)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$1$$anonfun$apply$2$$anonfun$apply$3.apply(VisitorRegistrationsSpec.scala:30)
[error] unit.models.VisitorRegistrationsSpec$$anonfun$1$$anonfun$apply$2$$anonfun$apply$3.apply(VisitorRegistrationsSpec.scala:30)

【问题讨论】:

  • 由于 Slick 基于 JDBC,Acolyte approach 可用于单元测试持久性。
  • 谢谢,但是根据 play 文档,这应该相对容易完成。由于这是可能会在游戏中构建的许多服务中的第一个,我们希望尽可能多地使用“游戏方式”

标签: scala playframework slick specs2


【解决方案1】:

副手,看起来好像你有一个初始化顺序问题。尝试将您的班级级别 vals 更改为 lazy valdef

【讨论】:

  • 这确实使 WithTestDb 中的 val profile = slick.driver.H2Driver 成为一个惰性值
猜你喜欢
  • 2015-04-06
  • 1970-01-01
  • 2011-01-10
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多