2012-12-26 232 views
5

this question所述,我正在研究一種方法,該方法返回一個List<FileInfo>中不存在於另一個List<FileInfo>中的元素。我實現了Nawfal的解決方案如下:爲什麼此CollectionAssert.AreEquivalent()測試失敗?

public List<FileInfo> SourceNotInDest(List<FileInfo> SourceFiles, List<FileInfo> DestFiles) 
{ 
var notInDest = SourceFiles.Where(c => !DestFiles.Any(p => p.Name == c.Name)).ToList(); 
return notInDest; 
} 

我對SourceFiles數據集是:

u:\folder1\a.txt 
u:\folder1\b.txt 
u:\folder1\c.txt 
u:\folder1\d.txt 

DestFiles是:

u:\folder2\a.txt 
u:\folder2\b.txt 
u:\folder2\c.txt 

當我單步執行代碼,並檢查清單'值,這似乎返回預期的結果。但單元測試失敗,出現以下的代碼:

public void SourceNotInDestTest() 
    { 
     //arrange 
     FileListComparer flc = new FileListComparer(); //class that has the list compare method 
     FolderReader fr = new FolderReader(); //class for getting FileInfo from folder 
     List<FileInfo> expectedResult = new List<FileInfo>(); 
     expectedResult.Add(new FileInfo(@"U:\folder1\d.txt")); 
     List<FileInfo> SourceFiles = fr.fileList(@"U:\folder1"); //gets the FileInfo for each file in the folder 
     List<FileInfo> DestFiles = fr.fileList(@"U:\folder2"); 


     //act 
     List<FileInfo> result = flc.SourceNotInDest(FTPFiles, LocalFiles); 

     //assert 
     CollectionAssert.AreEquivalent(result, expectedResult); 
    } 

即使resultexpectedResult具有相同的內容 - 這兩個列表具有相同的文件路徑和同其它特性的一個元件 - 測試失敗與消息:

CollectionAssert.AreEquivalent failed. The expected collection contains 1 occurrence(s) 
of <U:\folder1\d.txt>. The actual collection contains 0 occurrence(s). 

expectedResult確實有U:\folder1\d.txt發生,雖然。我想也許問題是我比較兩個對象的內存地址而不是這些對象的內容,但我認爲AreEquivalent()比較屬性。情況並非如此嗎?

編輯:基於有關比較,而不是地址屬性中的建議,我用這個斷言代替,這使得測試通過:

foreach (FileInfo fi1 in result) 
    { 
    Assert.IsNotNull(expectedResult.Find(fi2 => fi2.FullName == fi1.FullName)); 
    } 
foreach (FileInfo fi1 in expectedResult) 
    { 
    Assert.IsNotNull(result.Find(fi2 => fi2.FullName == fi1.FullName)); 
    } 

回答

7

大概是因爲FileInfo是引用類型和默認的比較只是檢查對於這兩個元素的地址是相等的。由於FileInfo是密封的,因此您無法從中派生並重寫相等比較器。在我看來,最好的選擇是編寫你自己的收集比較器方法(因爲你無法將IEqualityComparer實例傳遞給CollectionAssert.AreEquivalent)。

4

測試失敗,因爲您的集合中有不同的對象。如果您有兩個FileInfo類的實例引用同一個文件,並且您撥打instanceA.Equals(instanceB),則結果爲false

如果您可以更改您的代碼以使用字符串而不是FileInfo s,它將按照您的預期工作。

1

我可以建議2層的方法這比文件名的一個在我看來:)

  1. 選擇2集更好,並比較這些集合:

    CollectionAssert.AreEquivalent(
        result.Select(fi => fi.FullName).ToArray(), 
        expectedResult.Select(fi => fi.FullName).ToArray() 
    ); 
    // ToArray() is added just for better output when test fails. 
    
  2. 使用用戶定義比較和比較FileInfo列表:

    Assert.That(
        result, 
        Is 
         .EquivalentTo(expectedResult) 
         .Using((Comparison<FileInfo>)((fi1, fi2) => fi1.FullName.CompareTo(fi2.FullName))) 
    ); 
    

您當前implementaion有兩個foreach循環不會在以下情況下會失敗:

result = 
    u:\folder1\a.txt 
    u:\folder1\a.txt 

expectedResult = 
    u:\folder1\a.txt 

是的,這似乎並沒有對文件列表真實的案例,但generaly它不是一個好主意用兩個循環替換AreEquivalent()/Is.EquivalentTo()