2014-05-02 223 views
2

我有一個函數遍歷父對象的列表,並獲取for-each循環中每個父對象的子對象。要獲取子對象列表,該函數會調用另一個函數。這裏是功能:如何測試嵌套的foreach循環?

public IEnumerable<IParentObject> GetParentAndChildObjects() 
{ 
    var parentObjects = new List<ParentObject>(); 

    foreach (var item in _dbRepository.GetParentObjects()) 
    { 
     var parentObject = new ParentObject() { Id = item.ID, Name = item.Name }; 
     foreach (var subItem in _dbRepository.GetChildObjects(item.ID)) 
     { 
      parentObjects.Children.Add(new ChildObject() { Id = subItem.ID, Name = subItem.Name }); 
     } 
    } 
    return parentObjects; 
} 

我該如何寫這個函數的單元測試?我正在使用Moq進行嘲弄。

+2

offtopic:你永遠添加'parentObject'到'parentObjects'。你在'parentObjects'上調用'Children'而不是新創建的'parentObject'。所以你的代碼根本不能編譯(除非你有'Children'屬性的'List '實現)。 – MarcinJuraszek

+3

你模擬'_dbRepository'。 –

回答

0

事情是這樣的:

var repo = new Mock<MyRepository>(); 
repo.Setup(r => r.GetParentObjects()).Returns(... a list with a couple of parent objects ...); 
repo.SetUp(r => r.GetChildObjects(... id of first parent ...)).Returns(... list of child objects ...); 
repo.SetUp(r => r.GetChildObjects(... id of secondparent ...)).Returns(... different list of child objects ...); 

var result = new MyClass(repo.Object).GetParentAndChildObjects(); 

... assertions to check 2 parents with appropriate children returned ... 
0

通常情況下,你將創造內循環功能(可能是一個很好的事情,無論如何,爲便於閱讀和嵌套)。然後,一旦該功能就位,您可以爲其創建單元測試,就像您使用其他任何方法一樣。

如果由於某種原因您不想使用"Extract Method" refactoring(可以使用Resharper或其他重構工具自動執行),恐怕您運氣不好,因爲單元測試需要有一個入口點來測試你不能在另一種方法的中間輸入。

你可能會考慮的一件事,雖然它更多的維護,但有一個單元測試的調試版本和一個優化版本的循環內聯,使用#if。如果您在.NET 4.5或更高版本,你可以簡單地提取內環的方法和使用aggressive inlining of the method,而你沒有的高維護的提取方法的(潛在的)損失或性能的開銷。你可以使用

3

一種方法是測試內環以同樣的方式將一個私有方法。也就是說,你不(至少不是直接)。

相反測試循環本身的,確認是由GetParentAndChildObjects返回的結果。

通過指定_dbRepository的測試雙精度,您可以完全控制插入到parentObjects列表中的對象的詳細信息。因此,您的測試可以驗證返回的對象列表是否與預期一致。

Mark Seemann describes this approach well:

在已經回答了有關何時使用[存根以及何時使用嘲笑],幾次的問題,我來到這個簡單的規則,基於命令查詢分離的語言( CQS):

  • 使用嘲笑的命令

  • 使用存根查詢

這使得很多的意義,因爲命令是所有有關的副作用,並嘲弄都是關於行爲驗證:即,副作用發生。另一方面,存根主要存在於「發出快樂的噪音」,而他們必須這樣做的一種方式是在需要返回數據時從依賴關係返回數據。

+1

最佳答案imho,測試方法的功能,而不是底層的代碼結構。 – Nexus