2012-12-26 192 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()