2011-12-29 14 views
0

我有一個方法是採取我的實體框架實體並將其轉換爲一個DTO對象。在這種方法中,我有參數來跳過並限制要返回的相關項目的數量。對於小數據集是這樣一個簡單的查詢工作良好:單元測試時,導航屬性上調用.CreateSourceQuery()返回null;適用於實際的數據庫,我如何設置我的測試數據以匹配?

var query = this.AccessLogs 
    .Skip(skipRelated) 
    .Take(takeRelated); 

有了更大的數據集,我發現,這實際上執行SELECT *在我的數據庫,造成很多問題,因爲我在某些情況下,有上百萬的相關記錄。問this question後我修改查詢到這一點:

var query = this.AccessLogs 
    .CreateSourceQuery() 
    .OrderBy(p => p.ID) 
    .Skip(skipRelated) 
    .Take(takeRelated); 

現在,而這個固定的性能問題在集成測試我有,這引起我的單元測試失敗,每一個,因爲返回null,然後我.OrderBy()參數名稱爲source時出現ArgumentNullException的barfs。

我有一個存儲庫,它返回IQueryable<T>,我有依賴注入設置單元測試它,所以我設置我的「測試」數據是這樣的。最初我只是使用List<T>,但我發現this article它使用InMemoryObjectSet<T>進行測試。無論哪種方式,即使當數據在底層集合中時,我對的調用返回null。

IObjectSet<Parent> ret = new InMemoryObjectSet<Parent>(); 
var parent = new Parent(); 
parent.ID = 1; 
parent.Name = "Name 1"; 
for(int i = 0; i < 5; i++) 
{ 
    var ch = new Child(); 
    ch.ID = i; 
    ch.ParentID = 1; 
    ch.Property1 = "Name " + i.ToString(); 
    parent .Children.Add(ch); 
} 
ret.AddObject(parent); 

我的問題是:如何設置我的單元測試的測試數據,以便沒有返回null?

回答

1

你不會。如果您正在測試與EF相關的代碼,您必須使用真實的EF和真實的數據庫來完成此任務 - 這是沒有辦法解決的,任何嘗試避免它都等於not testing your application,但是有關EF應該如何工作的一些假設。

爲什麼在你的情況下不可能僞造? CreateSourceQueryEntityCollection的一種方法,實體集合依賴於真實的ObjectContext。在同一時間EntityCollection被密封。這種方法在任何公共接口中都不可用。所以沒有辦法用普通的單元測試API來取代它的邏輯。唯一的選擇是使用一些更先進的技術,這將允許您將方法調用重定向到其他方法(這僅由商用TypeMock Isolator和MS Moles提供),但這會導致您現在嘗試執行的相同問題=>測試你不擁有的代碼的假設。任何類型的僞造只有在您的測試不測試與EF相關的代碼,查詢或持久性時纔有意義 - 這些東西必須由單獨的集成測試覆蓋。

如何避免它?在您的測試類中創建新的方法:

protected virtual IEnumerable<AcessLog> GetLogs(int skipRelated, int takeRelated) 
{ 
    return this.AccessLogs. 
       .CreateSourceQuery() 
       .OrderBy(a => p.ID) 
       .Skip(skipRelated) 
       .Take(takeRelated); 
} 

現在,在您的測試不使用你原來的班,但派生類莫名其妙地覆蓋GetLogs方法,並返回你在測試的期望。

但是等等。我剛剛跳過GetLogs內部的邏輯測試,不是嗎?是的,我確實做到了。如上所述,此代碼不能進行單元測試。它必須使用真實數據庫進行單獨的集成測試,但是您將該代碼用單一方法隔離,並且可以通過僞造此方法對依賴於此方法的所有其他邏輯進行單元測試。

它仍然不會涵蓋你可以用CreateSourceQuery所遇到的所有問題。例如,如果您的關係已經加載會發生什麼?或者如果你的實體由於某種原因脫離了會發生什麼?那些副作用是不容易測試的。

+0

那麼,你會說這篇文章(http://blogs.msdn.com/b/adonet/archive/2009/12/17/walkthrough-test-driven-development-with-the-entity-framework- 4-0.aspx)和你鏈接的SO帖子是一樣的嗎?在中,沒有測試我的應用程序? – Nate 2011-12-29 20:31:58

+0

如果您要測試例如LINQ查詢,那麼這篇文章是錯誤的(它在許多其他部分是錯誤的,但與您的問題無關)。該文章針對EF的單一部分,您可以僞造某些東西,但所有其他EF部分都是剛性的。因爲它與你的問題無關 - 「CreateSourceQuery」不容易僞造。 – 2011-12-30 13:59:06

相關問題