为什么CollectionAssert.AreEquivalent()测试会失败?
本文关键字:失败 测试 CollectionAssert AreEquivalent 为什么 | 更新日期: 2023-09-27 17:49:32
如本问题所述,我正在研究一种方法,该方法返回一个List<FileInfo>
中不存在于另一个List<FileInfo>
中的元素。我已经实现了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;
}
我的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);
}
即使result
和expectedResult
有相同的内容——两个列表都有一个元素具有相同的文件路径和相同的其他属性——测试失败的消息:
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()
是比较属性。事实并非如此吗?
编辑:根据比较属性而不是地址的建议,我使用了这个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));
}
可能是因为FileInfo
是一个引用类型,默认比较器只是检查两个元素的地址是否相等。由于FileInfo
是密封的,因此不能从它派生并覆盖相等比较器。在我看来,最好的选择是编写自己的集合比较器方法(因为不能将IEqualityComparer
实例传递给CollectionAssert.AreEquivalent
)。
测试失败,因为集合中有不同的对象。如果你有两个实例的FileInfo
类引用同一个文件,你调用instanceA.Equals(instanceB)
,结果是false
。
如果你可以改变你的代码使用字符串而不是FileInfo
s,它会像你期望的那样工作。
我可以建议两种方法,在我看来比你的方法更好:)
-
选择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.
-
使用自定义比较器比较
FileInfo
列表:Assert.That( result, Is .EquivalentTo(expectedResult) .Using((Comparison<FileInfo>)((fi1, fi2) => fi1.FullName.CompareTo(fi2.FullName))) );
在以下情况下,使用两个foreach循环的当前实现不会失败:
result =
u:'folder1'a.txt
u:'folder1'a.txt
expectedResult =
u:'folder1'a.txt
是的,它似乎不是真正的情况下的文件列表,但一般来说,这不是一个好主意,以替换AreEquivalent()
/Is.EquivalentTo()
与两个循环。