测试 Play + Slick 应用
Testing Play + Slick app
我有一个使用 Scala Play 2.4.3
和 Play-slick 1.1.0
(slick 3.1.0
) 构建的简单 CRUD 应用程序,它使用 MySQL 数据库进行持久存储。
我正在尝试为我的应用程序创建测试,我看到了 2 个主要选项:
- 据我所知,模拟数据库访问需要一些代码更改
- 使测试使用替代数据库(可能在内存 H2 中)。
最好的方法是什么(优点和缺点)?
我更喜欢第二种方法,但我发现在设置测试时遇到了一些困难。
我需要做什么?首先,我认为我需要用 FakeApplication 进行测试 运行,对吗?我需要任何 sbt 依赖才能做到这一点吗?
之后如何指定使用H2数据库?
我遇到了同样的困难,我想出了这样的解决方案(使用第二种方法):
为 DAO 创建上下文以供使用:
trait BaseContext{
def dbName: String
val dbConfig = DatabaseConfigProvider.get[JdbcProfile](dbName)
val db = dbConfig.db
val profile = dbConfig.driver
val tables = new Tables { // this is generated by Schema Code Generator
override val profile: JdbcProfile = dbConfig.driver
}
}
@Singleton
class AppContext extends BaseContext{
def dbName = "mysql" // name in your conf right after "slick.dbs"
}
@Singleton
class TestingContext extends BaseContext{
def dbName = "h2"
}
然后创建一个模块来绑定注入,不要忘记在conf中启用它使用play.modules.enabled += "your.Module"
:
class ContextModule(environment: Environment, configuration: Configuration) extends AbstractModule {
override def configure(): Unit = {
if (configuration.getString("app.mode").contains("test")) {
bind(classOf[BaseContext])
.to(classOf[TestingContext])
} else {
bind(classOf[BaseContext])
.to(classOf[AppContext])
}
}
}
并将其注入到您创建的每个 DAO 中:
class SomeDAO @Inject()(context: BaseContext){
val dbConfig = context.dbConfig
val db = context.db
val tables = context.tables
import tables.profile.api._
def otherStuff....
// you can call db.run(...), tables.WhateverYourTableIs, tables.TableRowCaseClass, ...
}
最后一步,您的配置文件。在我的例子中,我使用 app.mode
来标记环境,我使用单独的 .conf
来标记不同的环境。当然,在这些 conf 中,您必须具有正确的数据库配置。这是示例:
app.mode = "test"
# Database configuration
slick.dbs = {
# for unit test
h2 {
driver = "slick.driver.H2Driver$"
db = {
url = "jdbc:h2:mem:test;MODE=MYSQL"
driver = "org.h2.Driver"
keepAliveConnection = true
}
}
}
我很确定我的解决方案不是一个优雅的解决方案,但它提供了货物。 :)
欢迎任何更好的解决方案!
我的解决方案是在每个规范的开头添加 step(Play.start(fakeApp))
,并在每个规范的末尾添加 step(Play.stop(fakeApp))
。
还有:
def fakeApp: FakeApplication = {
FakeApplication(additionalConfiguration =
Map(
"slick.dbs.default.driver" -> "slick.driver.H2Driver$",
"slick.dbs.default.db.driver" -> "org.h2.Driver",
"slick.dbs.default.db.url" -> "jdbc:h2:mem:play"
))
}
这是必需的,因为我正在使用 play-slick,它需要如下配置:
slick.dbs.default.driver = "slick.driver.MySQLDriver$"
slick.dbs.default.db.driver = "com.mysql.jdbc.Driver"
slick.dbs.default.db.url = "jdbc:mysql://localhost/database"
slick.dbs.default.db.user = "user"
slick.dbs.default.db.password = "password"
有关 docs
的更多信息
我有一个使用 Scala Play 2.4.3
和 Play-slick 1.1.0
(slick 3.1.0
) 构建的简单 CRUD 应用程序,它使用 MySQL 数据库进行持久存储。
我正在尝试为我的应用程序创建测试,我看到了 2 个主要选项:
- 据我所知,模拟数据库访问需要一些代码更改
- 使测试使用替代数据库(可能在内存 H2 中)。
最好的方法是什么(优点和缺点)?
我更喜欢第二种方法,但我发现在设置测试时遇到了一些困难。
我需要做什么?首先,我认为我需要用 FakeApplication 进行测试 运行,对吗?我需要任何 sbt 依赖才能做到这一点吗?
之后如何指定使用H2数据库?
我遇到了同样的困难,我想出了这样的解决方案(使用第二种方法):
为 DAO 创建上下文以供使用:
trait BaseContext{
def dbName: String
val dbConfig = DatabaseConfigProvider.get[JdbcProfile](dbName)
val db = dbConfig.db
val profile = dbConfig.driver
val tables = new Tables { // this is generated by Schema Code Generator
override val profile: JdbcProfile = dbConfig.driver
}
}
@Singleton
class AppContext extends BaseContext{
def dbName = "mysql" // name in your conf right after "slick.dbs"
}
@Singleton
class TestingContext extends BaseContext{
def dbName = "h2"
}
然后创建一个模块来绑定注入,不要忘记在conf中启用它使用play.modules.enabled += "your.Module"
:
class ContextModule(environment: Environment, configuration: Configuration) extends AbstractModule {
override def configure(): Unit = {
if (configuration.getString("app.mode").contains("test")) {
bind(classOf[BaseContext])
.to(classOf[TestingContext])
} else {
bind(classOf[BaseContext])
.to(classOf[AppContext])
}
}
}
并将其注入到您创建的每个 DAO 中:
class SomeDAO @Inject()(context: BaseContext){
val dbConfig = context.dbConfig
val db = context.db
val tables = context.tables
import tables.profile.api._
def otherStuff....
// you can call db.run(...), tables.WhateverYourTableIs, tables.TableRowCaseClass, ...
}
最后一步,您的配置文件。在我的例子中,我使用 app.mode
来标记环境,我使用单独的 .conf
来标记不同的环境。当然,在这些 conf 中,您必须具有正确的数据库配置。这是示例:
app.mode = "test"
# Database configuration
slick.dbs = {
# for unit test
h2 {
driver = "slick.driver.H2Driver$"
db = {
url = "jdbc:h2:mem:test;MODE=MYSQL"
driver = "org.h2.Driver"
keepAliveConnection = true
}
}
}
我很确定我的解决方案不是一个优雅的解决方案,但它提供了货物。 :) 欢迎任何更好的解决方案!
我的解决方案是在每个规范的开头添加 step(Play.start(fakeApp))
,并在每个规范的末尾添加 step(Play.stop(fakeApp))
。
还有:
def fakeApp: FakeApplication = {
FakeApplication(additionalConfiguration =
Map(
"slick.dbs.default.driver" -> "slick.driver.H2Driver$",
"slick.dbs.default.db.driver" -> "org.h2.Driver",
"slick.dbs.default.db.url" -> "jdbc:h2:mem:play"
))
}
这是必需的,因为我正在使用 play-slick,它需要如下配置:
slick.dbs.default.driver = "slick.driver.MySQLDriver$"
slick.dbs.default.db.driver = "com.mysql.jdbc.Driver"
slick.dbs.default.db.url = "jdbc:mysql://localhost/database"
slick.dbs.default.db.user = "user"
slick.dbs.default.db.password = "password"
有关 docs
的更多信息