2015-01-26 31 views
2

我正在研究一個新的Spring Batch(3.0.3.RELEASE)應用程序,其中在作業期間將訪問多個數據庫。爲了測試,我們使用HSQLDB(2.3.2)作爲嵌入式數據庫。構建期間出現jUnit錯誤時嵌入的多個HSQLDB數據庫

在我的應用程序上下文中,我有以下幾點。

<jdbc:embedded-database id="dataSource"> 
</jdbc:embedded-database> 

<jdbc:embedded-database id="proDataSource"> 
    <jdbc:script location="classpath:script-tables.sql" /> 
    <jdbc:script location="classpath:script-constraints.sql" /> 
</jdbc:embedded-database> 

<jdbc:embedded-database id="altDataSource"> 
    <jdbc:script location="classpath:script-alt-tables.sql" /> 
</jdbc:embedded-database> 

當我在Eclipse中運行單個測試時,情況很好。當我在命令行中建,第一次測試後,我得到的錯誤

Failed to execute SQL script statement at line 3 of resource class path resource [script-promrkt-promo.sql] 
object name already exists: PROMRKT 

在我看來,在EmbeddedDatabaseFactory填充過程中接收已填充的數據庫。從我可以告訴的是,每次測試後都沒有執行SHUTDOWN,並且HSQLDB正在將已填充的數據庫留在內存中。

我已重新審查文檔,並在Spring Doc這顯示一個明確的關機命令。但是,如果在我的測試開始時,彈簧啓動嵌入式數據庫,爲什麼測試完成後它不關閉?

  1. 預計嵌入式數據庫在相同的應用程序上下文的每個單元測試後都會保留嗎?
  2. 彈簧啓動嵌入式數據庫的順序是什麼,什麼時候初始化了事務上下文?
  3. 我需要使用數據庫清潔程序嗎?
  4. 能否填入被更新,以僅填充當數據庫第一次啓動,並回滾到原來的腳本配置我的測試完成時(有點像AbstractTransactionalSpringContextTests將如何工作)
  5. 我需要一些事務性的標記? Spring Batch的JobRepo在每次測試之間正確地被填充和銷燬。爲什麼我的自定義數據源不是?
+0

只是爲了確認,你不使用測試過程中任何類型的連接池?我問,因爲這個問題:https://jira.spring.io/browse/SPR-11372 – 2015-01-26 20:42:57

+0

不,連接池。至少我沒有明確表示要集合。我讀過這個問題,這可能是相關的。如果其中一條評論一次不會推薦一個嵌入式數據庫,那麼預測效果並不理想。我可以在哪裏實現Spring接口來修復/改善這種行爲的任何想法? – grbonk 2015-01-27 00:16:02

回答

3

日誌消息抱怨的腳本不在您的配置中。我認爲它正在其他地方執行?如果是這樣的話,你可能需要添加@DirtiesContext到你的測試中,這樣Spring就不會緩存上下文(我假設你使用的是SpringJunit4Runner@ContextConfiguration,但是不能確定,因爲你的實際測試不符合' t在問題中)。

如果我的假設是正確的,Spring會緩存上下文以提高單元測試套件運行的性能。如果您的測試以一種可能影響其他測試的方式修改上下文(例如在一個測試中運行腳本,需要在其他測試中再次運行腳本),則使用@DirtiesContext標記測試,並且Spring不會緩存上下文。您可以在方法或類級別使用註釋。你可以在這裏閱讀更多關於註解:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/annotation/DirtiesContext.html

1

我花了很多時間看着這個,閱讀Spring Framework文檔(gasp!)並通過代碼追蹤。 4.1彈簧核心有一些有趣的變化,特別是測試。

我發現ApplicationContext(s)現在緩存在JVM級別。如果第二個測試要求上下文,則TestContext首先在其緩存中查看是否有其他測試已經請求相同的配置。

我有一些配置文件爲我的一些測試。具有不同配置文件但具有相同@ContextConfiguration的測試會導致該上下文被重新加載到所應用的配置文件中。當「Bean Loader」到達創建嵌入式數據庫的時候,EmbeddedDatabaseFactory沒有考慮到嵌入式數據庫(在內存中的HSQLDB)可能已經被創建或者從以前的測試中緩存過來,並且不需要重新初始化。

因此,我在EmbeddedDatabaseFactory.initDatabase()中添加了一些邏輯,用於在重新初始化運行DatabasePopulator的&之前檢查數據庫是否已存在。

List existingDataBases = org.hsqldb.DatabaseManager.getDatabaseURIs(); 

    boolean isExisting = false; 
    String localDBName = StringUtils.lowerCase(this.databaseName); 

    for (Object object : existingDataBases) { 
     if (object.toString().contains(localDBName)) { 
      isExisting = true; 
      break; 
     } 
    } 

    // Now populate the database 
    if (!isExisting && this.databasePopulator != null) { 

(當然這不是需要什麼春天很潔淨,但它得到跨點)與EmbeddedDatabaseFactory和TestContext都會緩存機制

在我看來,它看起來像一個問題部分。我的「jdbc:embedded-database」定義沒有任何關聯的配置文件。爲什麼緩存需要重新創建它們,而不是將它們加載到現有的緩存bean之外?

0

每次創建新對象時,都可以通過設置唯一名稱generateUniqueName(true)來強制創建新的嵌入式數據庫。

下面是一個例子:

embeddedDatabase = new EmbeddedDatabaseBuilder() 
      .setType(EmbeddedDatabaseType.H2) 
      .generateUniqueName(true) 
      .addScripts("db/sql/create-db.sql", "db/sql/insert-data.sql") 
      .build();