利用HSQLDB進(jìn)行Hibernate單元測試

字號:

動機(jī)
    曾經(jīng)使用許多方法在數(shù)據(jù)庫和目標(biāo)代碼之間傳輸數(shù)據(jù)。從手動編碼的SQL到JDO,然后再到EJB,我從未找到一種特別喜歡的方法。自從采用測試驅(qū)動開發(fā)(TDD)作為指導(dǎo)原則以來,這種不滿情緒變得更加強(qiáng)烈。
    單元測試的障礙應(yīng)盡可能少。在關(guān)系數(shù)據(jù)庫中,障礙的范圍從外部依賴(數(shù)據(jù)庫在運行嗎?)到保持關(guān)系模型和對象模型同步的速度。由于這些原因,保持?jǐn)?shù)據(jù)庫訪問代碼與核心對象模型分離且無需涉及真實數(shù)據(jù)庫而進(jìn)行盡可能多的測試是很重要的。
    通常這會導(dǎo)致我們進(jìn)入下面兩種模式之一。第一種是具體化所有訪問域?qū)ο蟮臄?shù)據(jù)以及數(shù)據(jù)與單獨類或接口之間的關(guān)系。這就是典型的能夠檢索、編輯、刪除和添加域?qū)嶓w的數(shù)據(jù)存儲對象。這在單元測試中是最容易模擬出來的,但趨向于把域模型對象作為不帶有任何關(guān)系行為的純數(shù)據(jù)對象。直接從父對象訪問子記錄是最理想的,而不是將父對象處理為第三方類來決定子記錄。
    其他方法已經(jīng)使訪問接口的域?qū)ο筮M(jìn)入數(shù)據(jù)映射層(一種la Martin Fowler的數(shù)據(jù)映象模式)。這具有推動域模型中的對象關(guān)系的優(yōu)點,在域模型中,對象關(guān)系型接口只需表達(dá)一次即可。使用域模型的類不支持持久性機(jī)制,因為它本身內(nèi)在化到域模型中。這使代碼集中在設(shè)法解決的業(yè)務(wù)問題,而很少關(guān)注對象關(guān)系型映射機(jī)制。
    我的當(dāng)前項目涉及到處理大量的棒球統(tǒng)計數(shù)據(jù),并使用這些數(shù)據(jù)進(jìn)行模擬。因為數(shù)據(jù)已經(jīng)在關(guān)系數(shù)據(jù)庫中,所以對于我來說,有機(jī)會開發(fā)Hibernate對象關(guān)系型映射系統(tǒng)。我曾對Hibernate有很深刻的印象,但我遇到的一個問題是,在使用Hibernate進(jìn)行單元測試的數(shù)據(jù)映射時,設(shè)法插入一個間接層。該附加層非常脆弱,編寫起來感到非常困難。實際部署版本簡單地通過了特定于Hibernate的實現(xiàn)。更壞的情況是,模擬版本比真正的“產(chǎn)品級”版本更復(fù)雜,只因為模擬版本里沒有基本對象存儲器和帶有Hibernate的映射。
    我也使用很多復(fù)雜的Hibernate查詢,想要對應(yīng)用程序的重要部分進(jìn)行單元測試。然而,對活動的數(shù)據(jù)庫進(jìn)行測試不是好主意,因為這幾乎總是產(chǎn)生維護(hù)問題。另外,由于測試互相獨立,在測試上下文數(shù)據(jù)中使用相同的主鍵意味著必須在每次測試前創(chuàng)建代碼來清理數(shù)據(jù)庫,當(dāng)涉及到大量關(guān)系時就成為一個實際問題。
    通過使用HSQLDB和Hibernate強(qiáng)大的模式生成工具,能夠?qū)?yīng)用程序映射層進(jìn)行單元測試,并在對象查詢中找到不計其數(shù)的bug,這在以前手工測試時是做不到的。利用下面的技術(shù)概述,可以在開發(fā)過程中對整個應(yīng)用程序進(jìn)行測試,并且在測試有效區(qū)域內(nèi)沒有損害。