2011-09-21 78 views
2

這裏的掃描器:如何在沒有靜態測試數據庫的情況下使DAO類的單元測試更加脆弱?

我正在使用hibernate標準API來形成一些複雜的查詢來執行數據庫上的某些任務(例如跨多個字段的關鍵字搜索)的DAO對象。

我們需要對此進行單元測試,以確保生成的查詢對於各種情況都是正確的。測試它的一種方法 - 可能更可取 - 可能是通過在最後檢查並正確模擬數據庫交互來測試hibernate標準是否正確創建。然而,這並不可取,因爲它首先是有點作弊的(它只是重複代碼的工作),而且它不檢查標準本身是否會導致hibernate陷入困境,或者當它進入數據庫時​​會導致問題。

然後使用該選項對測試數據庫運行查詢。但是,由於歷史原因,沒有靜態測試數據庫(例如代碼中的代碼被檢入),而且我的項目的職責不允許我着手創建一個,我們必須滿足測試的要求共享開發數據庫,​​定期更新生產數據。

當這些刷新發生時,測試背後的數據也會發生變化,這會使我們的單元測試變得很脆弱。我們可以通過在測試中不使用確切的數字來克服它,但是這種方式測試不夠。

現在的問題是:人們在這種情況下做些什麼來減少測試的脆弱性?我想到的一個選擇是運行一個原生SQL,它執行相同的查詢(行爲上 - 不必與hibernate生成的查詢完全相同)以獲取期望的數字,然後運行DAO版本以查看如果匹配。這樣,查詢的行爲總是可以在初始本地SQL中實現,並且您將始終擁有正確的數字。

對這個或其他想法如何管理這種情況的任何反饋將不勝感激。

A.

UPDATE:

至於HSQLDB/H2 /德比的建議,我熟悉他們,但公司還沒有準備好,只是還沒有走這條路線,零碎做只有一個測試用例不適合。

至於我先前的建議,我想更詳細地說明一點 - 考慮這樣的場景:

我想確保我的相對複雜的關鍵字搜索返回的2100次比賽爲「約翰·史密斯」。

爲了找到預期的數字,我會分析我的數據庫,並使用SQL查詢找出數字。將該查詢作爲測試的一部分有什麼缺點,以便您始終知道您正在測試標準的行爲?

所以基本上是這樣一個問題:如果由於某種原因,你不能有一個靜態數據進行測試設置,你將如何執行你不脆的方式集成測試?

回答

5

我同意Andrey和Bedwyr的看法,長期來看最好的方法是創建專門用於測試的hsqldb數據庫。如果你沒有這個選擇,那麼你的解決方案看起來是一個合適的解決方案。你不能測試一切,但你也不想測試任何東西。我已經使用這種方法幾次來測試Web服務與集成數據庫等。但請記住,如果添加新列等,還必須維護此數據庫。

您必須決定要嘗試的內容去測試。你不想測試hibernate,你不想測試數據庫是否提供了你所要求的(用SQL來說)。在你的測試中,你可以假設休眠工作,就像數據庫一樣。

你說:

我們需要的單元測試是爲了確保生成的查詢是正確 各種場景。測試它的一種方式 - 可能是 更可取 - 將測試休眠條件創建 通過檢查它在最後並嘲笑數據庫 交互。然而,這不是理想的,因爲它首先是有點作弊(它只是複製代碼將做的事情),並且它也不檢查標準本身是否導致休眠,以致於無法訪問 ,或者當它進入數據庫時​​它會導致問題。

爲什麼要在hibernate barf上給你的標準呢?因爲你給它一個錯誤的標準。這不是hibernate的問題,而是創建條件的代碼。你可以在沒有數據庫的情況下測試。

它到達數據庫時有問題嗎?一般而言,Hibernate會創建適合您所提供的標準和數據庫方言的sql,因此,任何問題都與標準有關。

數據庫與休眠期望的不匹配?現在您正在測試標準和數據庫是否對齊。爲此,你需要一個數據庫。但是你不再測試標準,你正在測試所有東西都是一致的,一種不同的測試。

所以實際上,在我看來你正在做一個集成測試,從標準到數據庫結構的整個鏈都起作用。這是一個非常有效的測試。

所以,我所做的是在我的測試中創建另一個連接到數據庫(jdbc)來獲取信息。我執行SQL來獲取行數等,或檢查插入是否發生。

我認爲你的方法是完全有效的方法。

+0

非常感謝。是的,對於在正確的級別進行測試,您的觀點是絕對正確的,而且我們不在這裏測試hibernate或它的標準API。我試圖說明,只是測試以某種方式創建標準將是徒勞的,正如您所說的,我們需要測試從標準到結構到數據庫的整個鏈。這正是我所想的,你的評論對此很有幫助!乾杯。 –

3

然而,由於歷史的原因,沒有靜態測試數據庫(一個代碼簽入,例如代碼的一部分)和我的項目的職權範圍不允許我走上創建於

所有你需要做的是激發H2或類似的 - 把一些實體,並執行你的集成測試。一旦您完成了一些測試,您應該能夠提取一個數據設置實用程序,該實用程序創建一個包含一些測試數據的模式,如果您覺得需要,可以將其用於所有集成測試。

+0

感謝我的評論@Andrey Adamovich下面。你的建議都是有道理的,但我現在可能無法在現在完成事情的整體結構上做出改變。 –

6

一種方法可以是使用內存數據庫像Apache DerbyHSQLDB,並使用DBUnit測試開始前的數據與預填充它。

UPDATE:這是一個不錯的article關於這個問題。

+0

謝謝我熟悉hyperSQL db,dbunit和liquibase,並在過去多次使用過它們。但是,這是我目前在我們正在開展的小型項目範圍內無法進行的工作。 –

+0

在你的午餐時間,或在一小時前來。在你的機器上啓動並運行,然後演示給你的老闆,最好是通過測試來發現最近的錯誤。 – blank

+0

設置hsqldb,創建hibernate配置並添加setUp/tearDown方法來創建空數據庫,並指導你的單元測試不應該花太長時間。唯一可能需要更長時間的是創建DBUnit數據集。但是,您可以使用一些真實的數據庫從使用DBUnit的數據提取數據,或使用某個數據生成器來創建數據。 –

相關問題