2010-05-31 154 views
3

我的JUnit測試中有一個非常奇怪的問題,我似乎無法確定。我有一個具有相當標準結構的多模塊java webapp項目(DAO,服務分支等)。在這個項目中,我有一個'核心'項目,它包含一些抽象的設置代碼,它將一個測試用戶和必要的項目一起插入到用戶中(在這種情況下是一個'企業',因此用戶必須屬於企業,在數據庫級別)JUnit測試失敗 - 抱怨剛剛插入的缺失數據

相當簡單那麼遠,但這裏是哪裏的陌生感開始

  1. 一些測試無法運行,並拋出一個數據庫異常的地方抱怨用戶不能插入,因爲企業不存在。但它只是在前面的代碼行中創建了企業!企業的插入沒有錯誤。
  2. 陌生人,但如果這個測試類本身運行一切正常。只有當測試作爲項目的一部分運行時纔會失敗!
  3. 而完全相同的抽象代碼是在失敗之前通過10次測試運行的!
  4. ˚F

我一直在敲我的頭靠在這個牆上的天,真的沒有取得任何進展。我甚至不確定要提供哪些信息來幫助診斷此問題。

  • 使用JUnit 4.4,春季2.5.6,2.3.0的iBatis,PostgreSQL 8.3版本
  • 切換到org.springframework.jdbc.datasource.DriverManagerDataSource從org.apache.commons.dbcp.BasicDataSource改變的問題。使用DriverManagerDataSource,測試第一次工作,但現在突然間大量數據不會回滾到數據庫中!它使一切落後。當通過Eclipse & Maven的

運行,請詢問任何信息可以幫助我解決我的問題都沒有錯誤

  • 測試失敗!

    更新:我已經把記錄打開到最大。這次失敗的測試與另一次成功的測試只有一點區別。差異是突出顯示的。之後發生錯誤我看到一些「創建[java.util.concurrent.ConcurrentHashMap中]」線,然後將錯誤處理代碼開始

  • +0

    您可以在故障點檢查數據庫嗎?它實際上是否有企業記錄? – Yishai 2010-05-31 18:59:36

    +0

    可以給你提供你的db模型嗎.. – bragboy 2010-05-31 19:01:07

    回答

    0

    嗯......我似乎偶然發現了這個問題的解決方案,雖然我真的無法把握到底是什麼。我正在重建我的測試,通過全部移動它們,然後逐個恢復它們。低和看,直到我加入最後的測試類,問題再次出現

    該測試類擴展了基礎測試類,它定義了所有的Spring相關的設置註釋,如@RunWith和@ContextConfiguration。出於某種原因,此測試類重新定義了@RunWith和@ContextConfiguration屬性,並且一旦我將它們移除,事情又開始工作。關於這個測試類的另一個奇怪的事情是,我在每個測試中都使用@Ignore(它包含一些舊測試)。

    所以......如果有人曾經有這個奇怪的問題,您可以嘗試刪除多餘的註釋來修復它

    1

    這是一個硬需要解決的問題,但是我會根據你提供的細節進行猜測。

    假設:測試中的插入全部發生在一個事務中,該事務被回滾。 (這就是爲什麼BasicDataSource保持數據庫清潔的原因 - 它在最後回滾)。當停止發生時(通過使用DriverManagerDataSource)測試通過但數據庫不回滾。

    這表明即使「它只是在前面的代碼行中創建了企業!」該事務可以回滾以刪除該記錄。

    進一步假設(確定在狀態它,嘗試瘋狂猜測),某事(無論是在BasicDataSource或更可能是您自己的框架代碼)調用終結器中事務的回滾。這就是爲什麼它能夠工作10多次然後失敗,並且只是作爲項目的一部分 - 就是那個觸發當時垃圾回收的運行,導致事務回滾,導致新的代碼行開始新的事務記錄處於無效狀態。

    編輯:從您的編輯,似乎出於某種原因在失敗的測試你得到一個新的數據庫連接。這符合我上面的情況,但是也可以通過聲明由於某種原因在代碼中當測試作爲整個項目的一部分運行時獲得新的事務來解釋。新的交易沒有看到在不同的交易中發生的企業記錄的插入,並且交易保持開放和未提交。一種測試方法是將此運行時的事務隔離級別設置爲最大值,以便在事務處於有效狀態時無法掃描企業表。那麼如果這種情況是正確的,你的代碼就會死鎖。

    進一步編輯:我通過調用接近終結的意思是這樣的:

    public class SomeConnectionWrapper { 
         private Connection dbConnection; 
    
         protected void finalize() { 
          dbConnection.close(); 
         } 
    } 
    

    如果SomeConnectionWrapper被垃圾回收和關閉連接,數據庫連接池會返回一個不同的連接。

    +0

    謝謝你的幫助易hai。一個事務如何被回滾而沒有觸發回滾?即根本沒有錯誤,我不會引發回滾。 我剛把日誌記錄到最大值,只有一個區別,我可以看到這個失敗的測試和另一個就像它。我會在一分鐘後發佈這些結果 – 2010-05-31 20:46:33

    +0

    @Collin,正如我所說,我正處於野外猜測的領域。可以通過幾種方式在代碼中觸發回滾:關閉設置爲「autocommit:false」的數據庫連接或顯式回滾。我會檢查你的代碼,以確定關閉連接的終結器。 – Yishai 2010-05-31 20:59:02

    +0

    結果張貼在主要問題 – 2010-05-31 20:59:24

    1

    我跑進使用Junit4和春天有類似的問題。 爲了在提交之前從數據庫讀回內容,我必須將@Transactional添加到我的測試方法中。