不能 运行 在 h2 内存数据库上测试,而是 运行 在 PostgreSQL 上测试
Cannot run tests on h2 in-memory database, rather it runs on PostgreSQL
(我有多个相关问题,所以我将它们突出显示为粗体)
我有一个play app。
- 播放:2.6.19
- 斯卡拉:2.12.6
- h2: 1.4.197
- postgresql: 42.2.5
- play-slick/play-slick-evolutions: 3.0.1
- slick-pg: 0.16.3
我正在为 DAO 添加一个测试,我相信它应该 运行 在 h2 内存数据库上,该数据库在测试开始时创建,在测试结束时清除。
但是,我的测试总是在我配置和使用的 PostgreSQL 数据库上 运行s。
# application.conf
slick.dbs.default.profile="slick.jdbc.PostgresProfile$"
slick.dbs.default.db.driver="org.postgresql.Driver"
slick.dbs.default.db.url="jdbc:postgresql://localhost:5432/postgres"
这是我的测试test/dao/TodoDAOImplSpec.scala
。
package dao
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.test.{Injecting, PlaySpecification, WithApplication}
class TodoDAOImplSpec extends PlaySpecification {
val conf = Map(
"slick.dbs.test.profile" -> "slick.jdbc.H2Profile$",
"slick.dbs.test.db.driver" -> "org.h2.Driver",
"slick.dbs.test.db.url" -> "jdbc:h2:mem:test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE"
)
val fakeApp = new GuiceApplicationBuilder().configure(conf).build()
//val fakeApp = new GuiceApplicationBuilder().configure(inMemoryDatabase()).build()
//val fakeApp = new GuiceApplicationBuilder().configure(inMemoryDatabase("test")).build()
"TodoDAO" should {
"returns current state in local pgsql table" in new WithApplication(fakeApp) with Injecting {
val todoDao = inject[TodoDAOImpl]
val result = await(todoDao.index())
result.size should_== 0
}
}
}
对于 fakeApp
,我尝试了所有三个,但是 none 它们按预期工作 - 我的测试仍然 运行s 在我的本地 PostgreSQL table 上(其中有 3 个待办事项),因此测试失败。
我有tried/found:
首先,inMemoryDatabase()
简单地returns一张Map("db.<name>.driver"->"org.h2.Driver", "db.<name>.url"->""jdbc:h2:mem:play-test-xxx")
,看起来和我自己的conf
地图非常相似。但是,有两个主要区别:
inMemoryDatabase
使用 db.<name>.xxx
而我的 conf
地图使用 slick.dbs.<name>.db.xxx
。 哪一个应该是正确的?
其次,将 conf
地图的键重命名为 "slick.dbs.default.profile","slick.dbs.default.db.driver" 和 "slick.dbs.default.db.url" 将引发错误。
[error] p.a.d.e.DefaultEvolutionsApi - Unknown data type: "status_enum"; SQL statement:
ALTER TABLE todo ADD COLUMN status status_enum NOT NULL [50004-197] [ERROR:50004, SQLSTATE:HY004]
cannot create an instance for class dao.TodoDAOImplSpec
caused by @79bg46315: Database 'default' is in an inconsistent state!
这个发现很有趣 - 它与我使用 PostgreSQL ENUM 类型和 slick-pg? (See slick-pg issue with h2). Does it mean this is the right configuration for running h2 in-memory tests? If so, the question becomes How to fake PostgreSQL ENUM in h2.
有关吗
三、我跟着,运行sbt '; set javaOptions += "-Dconfig.file=conf/application-test.conf"; test'
附上一个测试配置文件conf/application-test.conf
:
include "application.conf"
slick.dbs.default.profile="slick.jdbc.H2Profile$"
slick.dbs.default.db.driver="org.h2.Driver"
slick.dbs.default.db.url="jdbc:h2:mem:test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE"
毫不奇怪,我得到了与第二次试验相同的错误。
在我看来,第二次和第三次试验指向了正确的方向(将在这方面发挥作用)。 但为什么我们必须将 name
设置为 default
? 还有其他更好的方法吗?
在游戏中默认数据库是default。但是,您可以将其更改为所需的任何其他数据库名称,但是您还需要添加数据库名称。例如,我想要一个 comment
数据库,其中包含 user
table:
CREATE TABLE comment.User(
id int(250) NOT NULL AUTO_INCREMENT,
username varchar(255),
comment varchar(255),
PRIMARY KEY (id));
然后我需要配置它才能连接到它(将它添加到 application.conf
文件):
db.comment.url="jdbc:mysql://localhost/comment"
db.comment.username=admin-username
db.comment.password="admin-password"
如上所述,您可以拥有用于测试的 test
数据库,并在测试中使用它。
本地数据库测试:为什么不像在生产环境中那样在本地拥有数据库呢?数据不存在,运行 本地测试没有触及生产数据库;为什么你需要一个额外的数据库?
Inconsistent State: 这是你写的 MYSQL 改变数据库中当前数据库的状态,这可能是基于创建一个新的table 或者当你想删除它时。
此外,status_enum
显然无法识别为 MySQL 命令。如果您不确定,请尝试在 MySQL 控制台中使用您想要使用的命令。
(我有多个相关问题,所以我将它们突出显示为粗体)
我有一个play app。
- 播放:2.6.19
- 斯卡拉:2.12.6
- h2: 1.4.197
- postgresql: 42.2.5
- play-slick/play-slick-evolutions: 3.0.1
- slick-pg: 0.16.3
我正在为 DAO 添加一个测试,我相信它应该 运行 在 h2 内存数据库上,该数据库在测试开始时创建,在测试结束时清除。
但是,我的测试总是在我配置和使用的 PostgreSQL 数据库上 运行s。
# application.conf
slick.dbs.default.profile="slick.jdbc.PostgresProfile$"
slick.dbs.default.db.driver="org.postgresql.Driver"
slick.dbs.default.db.url="jdbc:postgresql://localhost:5432/postgres"
这是我的测试test/dao/TodoDAOImplSpec.scala
。
package dao
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.test.{Injecting, PlaySpecification, WithApplication}
class TodoDAOImplSpec extends PlaySpecification {
val conf = Map(
"slick.dbs.test.profile" -> "slick.jdbc.H2Profile$",
"slick.dbs.test.db.driver" -> "org.h2.Driver",
"slick.dbs.test.db.url" -> "jdbc:h2:mem:test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE"
)
val fakeApp = new GuiceApplicationBuilder().configure(conf).build()
//val fakeApp = new GuiceApplicationBuilder().configure(inMemoryDatabase()).build()
//val fakeApp = new GuiceApplicationBuilder().configure(inMemoryDatabase("test")).build()
"TodoDAO" should {
"returns current state in local pgsql table" in new WithApplication(fakeApp) with Injecting {
val todoDao = inject[TodoDAOImpl]
val result = await(todoDao.index())
result.size should_== 0
}
}
}
对于 fakeApp
,我尝试了所有三个,但是 none 它们按预期工作 - 我的测试仍然 运行s 在我的本地 PostgreSQL table 上(其中有 3 个待办事项),因此测试失败。
我有tried/found:
首先,inMemoryDatabase()
简单地returns一张Map("db.<name>.driver"->"org.h2.Driver", "db.<name>.url"->""jdbc:h2:mem:play-test-xxx")
,看起来和我自己的conf
地图非常相似。但是,有两个主要区别:
inMemoryDatabase
使用db.<name>.xxx
而我的conf
地图使用slick.dbs.<name>.db.xxx
。 哪一个应该是正确的?
其次,将 conf
地图的键重命名为 "slick.dbs.default.profile","slick.dbs.default.db.driver" 和 "slick.dbs.default.db.url" 将引发错误。
[error] p.a.d.e.DefaultEvolutionsApi - Unknown data type: "status_enum"; SQL statement:
ALTER TABLE todo ADD COLUMN status status_enum NOT NULL [50004-197] [ERROR:50004, SQLSTATE:HY004]
cannot create an instance for class dao.TodoDAOImplSpec
caused by @79bg46315: Database 'default' is in an inconsistent state!
这个发现很有趣 - 它与我使用 PostgreSQL ENUM 类型和 slick-pg? (See slick-pg issue with h2). Does it mean this is the right configuration for running h2 in-memory tests? If so, the question becomes How to fake PostgreSQL ENUM in h2.
有关吗三、我跟着sbt '; set javaOptions += "-Dconfig.file=conf/application-test.conf"; test'
附上一个测试配置文件conf/application-test.conf
:
include "application.conf"
slick.dbs.default.profile="slick.jdbc.H2Profile$"
slick.dbs.default.db.driver="org.h2.Driver"
slick.dbs.default.db.url="jdbc:h2:mem:test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE"
毫不奇怪,我得到了与第二次试验相同的错误。
在我看来,第二次和第三次试验指向了正确的方向(将在这方面发挥作用)。 但为什么我们必须将 name
设置为 default
? 还有其他更好的方法吗?
在游戏中默认数据库是default。但是,您可以将其更改为所需的任何其他数据库名称,但是您还需要添加数据库名称。例如,我想要一个 comment
数据库,其中包含 user
table:
CREATE TABLE comment.User(
id int(250) NOT NULL AUTO_INCREMENT,
username varchar(255),
comment varchar(255),
PRIMARY KEY (id));
然后我需要配置它才能连接到它(将它添加到 application.conf
文件):
db.comment.url="jdbc:mysql://localhost/comment"
db.comment.username=admin-username
db.comment.password="admin-password"
如上所述,您可以拥有用于测试的 test
数据库,并在测试中使用它。
本地数据库测试:为什么不像在生产环境中那样在本地拥有数据库呢?数据不存在,运行 本地测试没有触及生产数据库;为什么你需要一个额外的数据库?
Inconsistent State: 这是你写的 MYSQL 改变数据库中当前数据库的状态,这可能是基于创建一个新的table 或者当你想删除它时。
此外,status_enum
显然无法识别为 MySQL 命令。如果您不确定,请尝试在 MySQL 控制台中使用您想要使用的命令。