2012-12-26 37 views
5

Wie in this question beschrieben, arbeite ich an einer Methode, die die Elemente von einem List<FileInfo>, die nicht in einem anderen List<FileInfo> vorhanden sind, zurückgibt. Ich habe Nawfal-Lösung wie folgt umgesetzt:Warum schlägt dieser CollectionAssert.AreEquivalent() Test fehl?

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

Meine Datensatz für Quelldateien ist:

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

DestFiles ist:

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

Wenn ich Schritt durch den Code und untersuchen die Listen 'Werte, dies scheint das erwartete Ergebnis zurückzugeben. Aber die Einheit Test nicht mit dem folgenden 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); 
    } 

Obwohl result und expectedResult haben den gleichen Inhalt - beide Listen ein Element mit dem gleichen Dateipfad und gleichen anderen Eigenschaften haben - der Test nicht erfolgreich mit der Meldung : obwohl

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

expectedResult ein Auftreten U:\folder1\d.txt hat. Ich dachte, dass das Problem vielleicht darin besteht, dass ich die Speicheradressen für zwei Objekte anstelle des Inhalts dieser Objekte vergleiche, aber ich dachte, die AreEquivalent() vergleicht Eigenschaften. Ist das nicht der Fall?

EDIT: Basierend auf dem Rat über Eigenschaften anstelle von Adressen zu vergleichen, habe ich dieses Assert statt, die der Test durchgelassen:

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

Antwort

7

Wahrscheinlich, weil FileInfo sind ein Referenztyp und der Standardvergleich nur Schecks die Adressen der beiden Elemente sind gleich. Da FileInfo versiegelt ist, können Sie nicht davon ableiten und die Gleichheitsvergleiche überschreiben. Die beste Option wäre meiner Meinung nach, Ihre eigene Vergleichs-Methode zu schreiben (da Sie eine IEqualityComparer Instanz nicht an CollectionAssert.AreEquivalent übergeben können).

4

Der Test schlägt fehl, da Ihre Sammlungen unterschiedliche Objekte enthalten. Wenn Sie zwei Instanzen der Klasse FileInfo haben, die sich auf dieselbe Datei beziehen, und Sie instanceA.Equals(instanceB) aufrufen, lautet das Ergebnis false.

Wenn Sie Ihren Code ändern könnten, um Zeichenfolgen anstelle von FileInfo s zu verwenden, würde es so funktionieren, wie Sie es erwarten.

1

Ich kann zwei Ansätze vorzuschlagen, die besser sind als Ihr eine meiner Meinung nach :)

  1. Select 2 Sammlungen von Dateinamen und vergleichen Sie diese Sammlungen:

    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. Verwendung benutzerdefiniert Vergleichen und vergleichen FileInfo Listen:

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

Ihre aktuelle implementaion mit zwei foreach-Schleifen wird nicht im folgenden Fall fehlschlagen:

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

expectedResult = 
    u:\folder1\a.txt 

Ja, es ist nicht wirklich der Fall für Dateien Liste zu sein scheint, aber generaly ist es nicht eine gute Idee, ersetzen Sie AreEquivalent()/Is.EquivalentTo() mit zwei Schleifen.

Verwandte Themen