2016-09-18 288 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