0

我們試圖弄清楚下面的代碼中單元測試對於基本情況的意義。做這個有益的單元測試嗎?我們並不試圖測試實體框架。我們只是想確保lambda表達式做它應該做的......我們的想法是,我們將使用DI來傳遞IQueryable的SOMETHING ..實際上它將是EF,但是對於單元測試並且將是POCO對象/集合。這有道理嗎?我們剛剛開始着手並希望在超越此基本代碼之前掌握這些概念。如何用lambda表達式進行單元測試實體框架/存儲庫模式

public class CongressRepository 
{ 
    CongressDb_DevEntities context = new CongressDb_DevEntities(); 

    CongressRepository(DbContext db) 
    { 
     context = (CongressDb_DevEntities) db; 
    } 

    public IQueryable<tMember> GetAllMembers 
    { 
     get { return context.tMembers; } 
    } 

    public IQueryable<tMember> GetVotingMembers 
    { 
     get { return context.tMembers.Where(x => x.age > 18); } 
    } 
} 
+0

Sooo你問我們是否應該單元測試這些方法?這些測試將會很快寫出來,如果你不熟悉寫測試,就不會習慣它們。我不明白你爲什麼特別提到lambda/EF,你到底有什麼疑問? –

+0

我們知道我們應該..我想這不是很清楚..我們問的是......我的意思是我們可以手動創建自動生成DbContext的東西的對象的集合......並將那些完全可查詢的與默認的EF DbContext行爲相同的方式? – punkouter

回答

1

對於使用DbContext的對象進行單元測試,您必須將其作爲接口注入到存儲庫對象中。請按照下列步驟:

1,創建一個包含所有的DbContext性質的接口,並從中派生的DbContext:

public interface ICongressDbContext { 
    IDbSet<Member> Members { get; set; } 
    // repeat for all dbsets 
} 

告訴上司這個接口在構造函數中你的資料庫。這是你的依賴注入:

private ICongressDbContext context; 
public CongressRepository(ICongressDbContext context){ 
    this.context = context; 
} 

你將要傳遞的上下文的實例中使用依賴注入框架像Autofac,也可以創建你實例化你的對象實例。

3.創建IDbSet的通用實現:https://gist.github.com/LukeWinikates/1309447。我們稱之爲FakeDbContext。

4.現在你有一個可模擬的接口和一個通用的DbSet實現,你可以創建你的模擬DbContext和你的模擬IDbSets。使用Moq,如下所示:

 var dataContext = new Mock<ICongressDbContext>(); 
     var members = new List<Member> { // create your test data here }; 
     // set up the mocked context to use your fake db set with test data 
     dataContext.SetupProperty(c => c.Members, new FakeDbContext<Member>(members)); 

     var repository = new CongressRepository(dataContext.Object); 

     // start writing your test methods here 

這將測試使用DbContext而不是DbContext本身的對象。
除了單元測試之外,您還需要編寫使用真實DbContext的集成測試。在訪問數據庫時,IQueryable支持許多不支持的方法。您還需要確保您的數據模型已正確映射到數據庫。

我希望這可以幫助您開始。

+0

好的。這似乎是要走的路線..即使line2objects不同於linq2ent ..也許它足夠接近 – punkouter

2

的原因之一爲單元測試代碼確保準確性...

在你的榜樣有人在他們的18歲生日或者它的任何和他們19歲生日的日子不能投票。我猜測它應該是:它涵蓋了一系列合理的成功和失敗值

public IQueryable<tMember> GetVotingMembers 
{ 
    get { return context.tMembers.Where(x => x.age >= 18); } 
} 

單元測試有助於確保您的代碼做什麼你就意味着:-)


但我們試圖找到一個爲什麼要問的是單元測試 的工作方式。

它可能是一個真正的痛苦! EF6剛剛發佈,使它更容易嘲笑DbContext,但現在需要很多設置...

重要的是,Linq-to-Etities和Linq-to-Objects之間存在差異,所以你確實需要單元測試和集成測試。

有很多博客和SO questions相關,雖然...使用FakeDbSet作爲一些谷歌福的起點。

+1

你的代碼與他的差別如何? –

+0

Doh!漫長的一天: -/ –

+1

是的。我們知道我們應該單元測試。這對於初學者來說是一個很好的例子..但是我們試圖找到一個爲什麼要問的是單元測試的工作原理...... EF與手動EF?我們很難找到一種方法來解釋這個...我們正在嘗試UNIT測試..而不是INTEGRATION測試 – punkouter

5

EF使用LINQ to Entities,但是當嘲笑EF時你會切換到LINQ to Objects。這可能會導致您的單元測試誤報,因爲在LINQ to Entities和LINQ to Objects之間存在差異。沒有集成測試,您只會在生產環境中看到這些差異/錯誤。

+0

那麼你是說人們通常這樣做的方式是模擬執行查詢的對象,然後將剩餘的代碼單元化?在GetAllMembers()的情況下,在MOCK之後沒有任何代碼留下了......因此,我想我不會單元測試這種方法嗎? – punkouter

+0

在TDD中,只有在進行測試之後才能使用該方法。測試將描述GetAllMembers結果應該用於已知數據。這有助於防止未來意想不到的副作用發生變化...... –

相關問題