2016-09-18 287 views
1

我想在内存数据库使用此代码运行我的测试:Scala play:H2“HikariDataSource已关闭。”

class MySpec extends PlaySpec with OneAppPerSuite { 

    Databases.withInMemory(
    name = "test", 
    urlOptions = Map(
     "MODE" -> "MYSQL", 
     "DATABASE_TO_UPPER" -> "false", 
     "DB_CLOSE_DELAY" -> "-1" 
    ), 
    config = Map(
     "logStatements" -> true, 
     "lazyInit" -> true, 
     "username" -> "sa", 
     "password" -> "" 
    ) 
) { TestDb => 

    "DataManagementController" should {"connect" in { 
     TestDb.withConnection(conn => 0) // do nothing, but connect 
    }} 

    } 
} 

,但我收到此错误:执行测试之前“HikariDataSource已关闭”:

[info] DataManagementController 
[info] - should connect *** FAILED *** 
[info] java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed. 
[info] at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:79) 
[info] at play.api.db.DefaultDatabase.getConnection(Databases.scala:142) 
[info] at play.api.db.DefaultDatabase.withConnection(Databases.scala:152) 
[info] at play.api.db.DefaultDatabase.withConnection(Databases.scala:148) 
[info] at ControllerSpec$$anonfun$1$$anonfun$apply$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(ControllerSpec.scala:37) 
[info] at ControllerSpec$$anonfun$1$$anonfun$apply$1$$anonfun$apply$mcV$sp$1.apply(ControllerSpec.scala:37) 
[info] at ControllerSpec$$anonfun$1$$anonfun$apply$1$$anonfun$apply$mcV$sp$1.apply(ControllerSpec.scala:37) 
[info] at org.scalatest.Transformer$$anonfun$apply$1.apply$mcV$sp(Transformer.scala:22) 
[info] at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85) 
[info] at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) 
[info] ... 

我在做什么错?

回答

1

当您使用OneAppPerSuite,游戏会为每间套房启动一个应用实例。在你的情况下,你正在创建一个测试数据库,在应用程序准备就绪之前。所以,你必须在你的代码的顺序颠倒的东西是这样的:

"DataManagementController" should { 
    "connect" in { 
     Databases.withInMemory(
      // Options and config here 
     ) { TestDb => 
      TestDb.withConnection(conn => 0) 
     } 
    } 
} 

您也可以封装在数据库初始化部分,使之更容易在需要的是DB每个测试使用:

def testDB[T](block: Database => T) = { 
    Databases.withInMemory(
     name = "test", 
     urlOptions = Map(
     "MODE" -> "MYSQL", 
     "DATABASE_TO_UPPER" -> "false", 
     "DB_CLOSE_DELAY" -> "-1" 
    ), 
     config = Map(
     "logStatements" -> true, 
     "lazyInit" -> true, 
     "username" -> "sa", 
     "password" -> "" 
    ) 
    ) { block } 
    } 

然后用它是这样的:

"DataManagementController" should { 
    "connect" in { 
     testDB { db => db.withConnection(conn => 0) } 
    } 
} 

来源:https://www.playframework.com/documentation/2.5.x/ScalaTestingWithDatabases

+0

谢谢!有用。你知道这种做法(为每个测试创建一个数据库实例)是否会增加性能开销/建议吗? – JulienD

+1

是的,它确实(增加了开销)。在一般情况下,我认为这是可取的,每个测试有它的分贝,所以他们是独立的(即没有测试,在可以影响另一种方式变化的数据)。当然,如果你有很多测试,创建所有这些数据库将需要一些时间(特别是如果你应用迁移/种子数据)。你将不得不找到更适合你的东西。也许具有所有的测试,每间套房初始化,再利用一个数据库可以工作得很好(当然,如果你确保其他人需要一个测试不删/更新数据...) – Salem