2016-05-18 28 views
7

注意:

我很樂意爲這個問題提供一個更好的標題。如何驗證沒有數據庫的LINQ查詢


背景:

對於任何人誰曾與實體框架足夠長的工作,你一定會遇到一個問題,即產生IQueryable<T>是無法通過數據庫來執行。這源於IQueryable<T>不可能完全實現,除了內存實現(如LINQ to objects)之外。諸如C#方法調用並使用Single/SingleOrDefault作爲非最終查詢操作可能會在發送到實際的IQueryProvider(例如MSSQL或Oralce)時導致失敗,但會通過單元測試。

我目前知道如何測試這些情況的唯一方法是實際運行該軟件。雖然我同意軟件應該作爲編寫新查詢(或者一般新代碼)的一部分來完成,但如果可以使用單元測試找到這些類型的錯誤,這將會很有幫助。導致我在這裏的事件發現了一個新的錯誤,我確信開發者雖然是一個無辜的和安全的變化。更進一步,大量的單元測試通過了錯誤的信心。


問:

是否可以驗證所產生的IQueryable<T>其實可以在一個特定的數據庫技術(MSSQL,甲骨文,等...)從單元測試運行?


例子:

可查詢與C#方法調用:

var result = (
    from a in session.Query<A> 
    where a.Field == SomeFunction(a) 
    select a 
    ).ToList(); 

這將失敗不能夠執行C#代碼數據庫的明顯的原因。


可查詢與單

var result = (
    from a in session.Query<A> 
    where a.Field == session.Query<B>().Single().Field 
    select a 
    ).ToList(); 

這將失敗歸因於單一用途作爲非最終的查詢操作。


還有其他的情況,但我想上面的兩個例子描述了我試圖能夠檢測到的東西。

+1

我們使用「單元測試」,需要一個乾淨的數據庫設置。我們的測試設置會插入測試數據,拆卸將會刪除它。它們不是真正的單元測試,因爲它們需要數據庫連接,但它們也不是完整的功能測試。 – GendoIkari

+2

@GendoIkari這些測試稱爲集成。 – Karolis

+0

@mhand我不知道答案。但你的問題是我見過的最好的準備好的問題。希望這個問題可以給你一些想法http://stackoverflow.com/questions/6599805/unit-test-iqueryable – yyou

回答

0

您必須在單元測試中模擬像session.Query<A>這樣的屬性併發送一個enumerable\queryable集合。根據我的經驗,這樣做的好處不足以創建和維護這些類型的測試,特別是在涉及多個表和圖層的複雜查詢時。

儘管我發現有用的(用於測試實際查詢),但更多的集成測試使用框架,如specflow,您可以輕鬆設置測試數據並執行集成測試,同時測試比單元測試更高級別的軟件行爲。但是當然這些應該適用於真正的數據庫,所以你可能不希望他們開始。

1

有了這個查詢

var query = 
    from a in session.Query<A> 
    where a.Field == session.Query<B>().Single().Field 
    select a; 

執行

query.ToString(); 

,如果它不能被翻譯成正確的SQL查詢時,它會拋出異常。

+0

有趣的方法。我看到的主要問題是它需要訪問'IQueryable '實例。我想我是希望實現'IQueryProvider',它可以在查詢生成時檢查查詢。 – mhand

+0

如果這是你關心的問題,它不會運行實際查詢。 –