尝试在 Scala 中为 Play Web 应用程序的 Slick 数据库创建单元测试
Posted
技术标签:
【中文标题】尝试在 Scala 中为 Play Web 应用程序的 Slick 数据库创建单元测试【英文标题】:Trying to create Unit tests for Slick database for Play web application in Scala 【发布时间】:2018-02-02 12:52:20 【问题描述】:我正在努力尝试使用 Scala 为我的 Play Web 应用程序配置单元测试。我正在使用 Play 2.6 和 Scala 2.11.8。当我使用数据库配置并执行sbt test
时,我在控制台上收到错误No implementation for play.api.db.slick.DatabaseConfigProvider was bound
。所以我将展示我如何设置我的网络应用程序,也许有人可以指出哪里出了问题。只是为了方便起见,Web 应用程序运行良好。这只是我无法创建的数据库的单元测试。
build.sbt
import play.sbt.PlayImport._
name := """crypto-miners-demo"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.8"
libraryDependencies += guice
libraryDependencies += evolutions
libraryDependencies += jdbc
libraryDependencies += filters
libraryDependencies += ws
libraryDependencies += "com.h2database" % "h2" % "1.4.194"
libraryDependencies += "com.typesafe.play" %% "anorm" % "2.5.3"
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.0" % Test
libraryDependencies += "com.typesafe.play" %% "play-slick" % "3.0.0"
libraryDependencies += "com.typesafe.play" %% "play-slick-evolutions" % "3.0.0"
libraryDependencies += "org.xerial" % "sqlite-jdbc" % "3.19.3"
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.2.0"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.2.0"
dependencyOverrides += "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.5"
application.conf:
play.application.loader = di.ApplicationLoader
play.filters.csrf.header.bypassHeaders
X-Requested-With = "*"
Csrf-Token = "nocheck"
play.filters.csrf.bypassCorsTrustedOrigins = false
play.filters.disabled += play.filters.csrf.CSRFFilter
slick.dbs.default.profile = "slick.jdbc.SQLiteProfile$"
slick.dbs.default.db.driver = "org.sqlite.JDBC"
slick.dbs.default.db.url = "jdbc:sqlite:development.db"
slick.dbs.default.db.username = ""
slick.dbs.default.db.password = ""
db.default
driver = org.sqlite.JDBC
url = "jdbc:sqlite:development.db"
username = ""
password = ""
play.modules.disabled += "play.api.db.DBModule"
RackRepositorySpec.scala:
import org.scalatestplus.play.PlaySpec
import org.scalatestplus.play.guice.GuiceOneAppPerTest
import play.api.db.evolutions._
import play.api.db.slick.DatabaseConfigProvider
import play.api.db.Database, Databases
import play.api.inject.bind
import play.api.inject.guice.GuiceInjectorBuilder
import play.api.test.Injecting
class RackRepositorySpec extends PlaySpec with GuiceOneAppPerTest with Injecting
val database = Databases(
driver = "org.sqlite.JDBC",
url = "jdbc:sqlite:development.db",
name = "default",
config = Map(
"username" -> "",
"password" -> ""
)
)
val guice = new GuiceInjectorBuilder()
.overrides(bind[Database].toInstance(database))
.injector()
val defaultDbProvider = guice.instanceOf[DatabaseConfigProvider]
def beforeAll() = Evolutions.applyEvolutions(database)
def afterAll() =
// Evolutions.cleanupEvolutions(database)
database.shutdown()
Evolution(
1,
"create table test (id bigint not null, name varchar(255));",
"drop table test;"
)
当我执行 sbt test
时出现此错误:
[info] models.RackRepositorySpec *** ABORTED ***
[info] com.google.inject.ConfigurationException: Guice configuration errors:
[info]
[info] 1) No implementation for play.api.db.slick.DatabaseConfigProvider was bound.
[info] while locating play.api.db.slick.DatabaseConfigProvider
[info]
[info] 1 error
[info] at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1045)
[info] at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
[info] at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:409)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:404)
[info] at play.api.inject.ContextClassLoaderInjector$$anonfun$instanceOf$2.apply(Injector.scala:117)
[info] at play.api.inject.ContextClassLoaderInjector.withContext(Injector.scala:126)
[info] at play.api.inject.ContextClassLoaderInjector.instanceOf(Injector.scala:117)
[info] at models.RackRepositorySpec.<init>(RackRepositorySpec.scala:26)
[info] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
【问题讨论】:
你可以看看acolyte.eu.org 【参考方案1】:我在 build.sbt 中使用 libraryDependencies += specs2 % Test
解决了问题。我希望这是 slick 的一个好习惯:
import org.specs2.mutable.Specification
import play.api.Application
import play.api.test.WithApplicationLoader
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await, Future
import scala.concurrent.duration.DurationInt
class RackRepositorySpec extends Specification
"RackRepository" should
"work as expected" in new WithApplicationLoader
val app2dao = Application.instanceCache[RackRepository]
val rackRepository: RackRepository = app2dao(app)
Await.result(rackRepository.delete("r-1"), 3 seconds)
Await.result(rackRepository.delete("r-2"), 3 seconds)
Await.result(rackRepository.delete("r-3"), 3 seconds)
val testRacks = Set(
RackRow("r-1", 0.2F, System.currentTimeMillis()),
RackRow("r-2", 0.5F, System.currentTimeMillis()),
RackRow("r-3", 0.8F, System.currentTimeMillis())
)
Await.result(Future.sequence(testRacks.map(rackRepository.insert)), 3 seconds)
val storedRacks = Await.result(rackRepository.list(), 3 seconds)
storedRacks.toSet must contain(testRacks)
【讨论】:
以上是关于尝试在 Scala 中为 Play Web 应用程序的 Slick 数据库创建单元测试的主要内容,如果未能解决你的问题,请参考以下文章
在 Play 2.1 和 Scala 中为文件上传编写测试用例
在 Play Framework 2.4 中为 Scala 实现 CORS
如何将 Play 2.2 Scala 应用程序创建为 SBT 子项目