简体   繁体   English

为什么这个CollectionAssert.AreEquivalent()测试失败了?

[英]Why does this CollectionAssert.AreEquivalent() test fail?

As described in this question , I'm working on a method that returns the elements from one List<FileInfo> that are not present in another List<FileInfo> . 正如在这个问题中所描述的那样,我正在研究一种方法,它返回一个List<FileInfo>中不存在于另一个List<FileInfo>的元素。 I've implemented Nawfal's solution as follows: 我已经实现了Nawfal的解决方案如下:

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;
}

My data set for SourceFiles is: 我为SourceFiles设置的数据是:

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

DestFiles is: DestFiles是:

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

When I step through the code and examine the lists' values, this appears to return the expected result. 当我单步执行代码并检查列表的值时,这似乎返回预期的结果。 But the unit test fails with the following code: 但单元测试失败,代码如下:

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);
    }

Even though result and expectedResult have the same contents--both lists have one element with the same file path and same other properties--the test fails with the message: 即使resultexpectedResult具有相同的内容 - 两个列表都有一个具有相同文件路径和相同其他属性的元素 - 测试失败并显示以下消息:

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

expectedResult does have an occurrence of U:\\folder1\\d.txt , though. expectedResult确实出现了U:\\folder1\\d.txt I was thinking maybe the problem is that I'm comparing the memory addresses for two objects instead of the contents of those objects, but I thought the AreEquivalent() was comparing properties. 我想也许问题是我正在比较两个对象的内存地址而不是那些对象的内容,但我认为AreEquivalent()正在比较属性。 Is that not the case? 那不是这样吗?

EDIT: Based on the advice about comparing properties instead of addresses, I used this Assert instead, which allowed the test to pass: 编辑:基于有关比较属性而不是地址的建议,我使用了此Assert,这允许测试通过:

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));
    }

Probably because FileInfo is a reference type and the default comparer just checks for the two elements' addresses to be equals. 可能是因为FileInfo是一个引用类型,默认的比较器只是检查两个元素的地址是否相等。 Since FileInfo is sealed, you can't derive from it and override the equality comparers. 由于FileInfo是密封的,因此您无法从中派生并覆盖相等比较器。 The best option, in my opinion, would be writing your own collection comparer method (since you can't pass an IEqualityComparer instance to CollectionAssert.AreEquivalent ). 在我看来,最好的选择是编写自己的集合比较器方法(因为你不能将IEqualityComparer实例传递给CollectionAssert.AreEquivalent )。

The test is failing because your collections have different objects in them. 测试失败,因为您的集合中包含不同的对象。 If you have 2 instances of the FileInfo class that refer to the same file, and you call instanceA.Equals(instanceB) , the result is false . 如果您有2个引用同一文件的FileInfo类实例,并且您调用instanceA.Equals(instanceB) ,则结果为false

If you could change your code to use strings instead of FileInfo s, it would work as you expect it to. 如果您可以将代码更改为使用字符串而不是FileInfo ,那么它将按预期工作。

I can suggest 2 approaches which are better than your one in my opinion :) 在我看来,我可以建议两种比你的方法更好的方法:)

  1. Select 2 collections of file names and compare these collections: 选择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. Use user-defined comparer and compare FileInfo lists: 使用用户定义的比较器并比较FileInfo列表:

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

Your current implementaion with two foreach loops won't fail in the following case: 在下列情况下,您当前使用两个foreach循环的实现不会失败:

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

expectedResult =
    u:\folder1\a.txt

Yeah, it doesn't seem to be real case for files list, but generaly it is not a good idea to replace AreEquivalent() / Is.EquivalentTo() with two loops. 是的,对于文件列表来说似乎并不真实,但通常用两个循环替换AreEquivalent() / Is.EquivalentTo()并不是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM