2011-09-30 78 views
1

我有一個簡單的標準存儲庫,從數據庫加載一個複合實體。它通過IDbConnection(我們可以模擬知識庫訪問IDbCommand,IDbTransaction,IDataReader)注入從數據庫中讀取完整實體樹所需的所有依賴關係。單元測試,以驗證存儲庫從數據庫正確加載實體

public class SomeCompositionRootEntityRepository : 
    IRepository<SomeCompositionRoot> 
{ 
    public RecipeRepository(IDbConnection connection) { ... } 
    public void Add(SomeCompositionRootEntity item) { ... } 
    public bool Remove(SomeCompositionRootEntity item) { ... } 
    public void Update(SomeCompositionRootEntity item) { ... } 
    public SomeCompositionRootEntity GetById(object id) { ... } 
    public bool Contains(object id) { ... } 
} 

問題是,我將如何編寫單元測試的這個好方法?如果我想測試一下reposity已經讀取了整個對象樹,並且它已經讀取了它的正確性,我需要編寫一個hughe mock來記錄和驗證樹中每個對象的每個屬性的讀取。這真的是要走的路嗎?

更新: 我想我需要重構我的存儲庫,以便將存儲庫功能和單元測試分解爲更小的單元。這怎麼能做到?

我確定我不想編寫涉及從實際數據庫讀寫數據的單元測試。

回答

1

的問題是:你要測試什麼功能?

  1. 是否要測試您的存儲庫是否實際加載了某些內容?在這種情況下,我會寫一些(!)通過數據庫的測試。
  2. 還是要測試存儲庫方法內的功能?在這種情況下,你的模擬方法是適當的。
  3. 還是你想確保你的倉庫的(平凡的)方法沒有被破壞?在這種情況下,模擬和每種方法一次測試可能就足夠了。

只問問自己測試應該確保什麼,並沿着這個目標設計它們!

+0

對於任何給定的'SomeCompositionRootEntity'我想測試它讀取所有對象和子對象,讀取屬性所需的所有列,正確組裝對象樹,寫入所有對象,寫入所有屬性。由於這棵樹相當複雜,我似乎必須寫出幾個非常龐大而龐大的單元測試。我想要正確的東西嗎? – bitbonk

+0

所有這些功能都是在倉庫的方法中編碼的嗎?如果是這樣,你應該考慮分開測試方法來單獨測試零件。簡單的簡短方法很好。如果此功能是從外部提供的(例如來自關係映射程序),則不應該對其進行詳細測試。 – Arne

+0

我在.NET 2.0中,我不想使用任何第三方ORM。這種功能如何分解? – bitbonk

0

我想我明白你的問題,以便糾正我,如果我錯了......

這是你越線從單元到整合。測試是有意義的(我自己寫了這些),但是你並沒有真正測試你的存儲庫,而是測試你的實體(SomeCompositionRoot)正確映射。它不是插入/更新,而是涉及對數據庫的讀取。

根據您使用的ORM,您可以通過一百萬種不同的方式完成此操作,並且通常非常簡單。

::編輯:: 這樣的LINQ例如...

[TestMethod] 
    public void ShouldMapBlahBlahCorrectly() 
    { 
     CheckBasicMapping<BlahBlah>(); 
    } 

    private T CheckBasicMapping<T>() where T : class 
    { 
     var target = _testContext.GetTable<T>().FirstOrDefault(); 
     target.ShouldNotBeNull(); 
     return target; 
    } 
+0

我在.NET 2.0中,我不使用任何映射器。該存儲庫完成了所有使用「IDataReaders」和「IDbCommands」的工作。我應該重構存儲庫並引入某種映射器類,對象樹中的每個實體類型都有一個類? – bitbonk

+0

儘管它很糟糕,但它可能是值得的。讓T實現一些像「IMap」之類的接口,並允許它定義T的構造並讓庫調用該函數/方法 – jeriley