2016-08-11 1 views
0

Ich habe eine (enum: int) AccessOptions, die verwendet wird, um ein Dictionary zu füllen, um einfache Zugriffeigenschaften für eine indizierte Liste von Benutzerprinzipalnamen widerzuspiegeln.custom == für Dictionary-Erweiterung denkt, dass sie leer sind

Ich brauchte Unit-Tests zu unterstützen -

Assert.AreEqual 
    <Dictionary<string, AccessOptions>, 
    Dictionary<string, AccessOptions>) 

... speziell die chaotisch ist, und ruft den Gleichheitsoperator Sprache generic, die wirklich nur Referenzwerte überprüft - was ich brauche ist, dass zwei verschiedene zu etablieren Referenzobjekte enthalten dieselben Schlüssel nach Wert, und dass die zugehörigen Werte dieser Schlüssel jeweils übereinstimmen.

Also habe ich meinen eigenen Gleichheitsoperator geschrieben und eine Klasse erstellt, die das Dictionary erweitert, um zu vermeiden, Wörterbuchobjekte in meinem Projekt zu vermasseln. Wenn diese Methode in Visual Studio 2016 im Kontext des Debuggens eines Assert.AreEqual-Aufrufs eines Komponententests ausgeführt wird, gehen einige Dinge seitwärts und ich markiere sie unten mithilfe von Kommentaren.

 public class SecretAccessRuleSet : Dictionary<string, AccessOptions> 
{ 
    public SecretAccessRuleSet() {} 

    public SecretAccessRuleSet(int size) : base (size) {} 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     return obj.GetType() == GetType() && Equals((SecretAccessRuleSet) obj); 
    } 

    public static bool operator == (SecretAccessRuleSet a, SecretAccessRuleSet b) 
    { 
     if (ReferenceEquals(a, b)) 
     { 
      return true; 
     } 

     /* When the below statement executes in debug, I can watch 
     * execution flow from the equality test against (object)a, 
     * straight to "return false" -- but execution does not actually 
     * return, but appears to jump directly to the foreach statement 
     * two blocks down. It might be important, or just a bug. 
     */ 
     if (((object)a == null) || ((object)b == null)) 
     { 
      return false; 
     } 

     if (a.Count != b.Count) 
     { 
      return false; 
     } 

     /* Then when we get here, the visualizer highlights a; I advance 
     * one line and it highlights "in", which I assume is wherein an 
     * enumerator is initialized; I advance again and we jump to the 
     * end of the method! Literally to the end curly brace. 
     */ 
     foreach (var entry in a) 
     { 
      AccessOptions bOpt; 
      if (!b.TryGetValue(entry.Key, out bOpt) 
       || bOpt != entry.Value) 
      { 
       return false; 
      } 
     } 

     // If we get here, they're equal 
     return true; 
    } 

    public bool Equals(SecretAccessRuleSet other) 
    { 
     return this == other; 
    } 

    public static bool operator !=(SecretAccessRuleSet a, SecretAccessRuleSet b) 
    { 
     return !(a == b); 
    } 

    public override int GetHashCode() 
    { 
     return base.GetHashCode(); 
    } 
} 

Die Testergebnisse zeigen, dass die Assert.AreEqual (a, b) Aufruf falsch zurück, aber ich habe sehr geringen Glauben, dass der Inhalt entweder Sammlung ausgewertet wurde, und ich verstehe nicht, warum.

Ich werde wahrscheinlich all das entfernen und eine separate Möglichkeit schaffen, diese zu testen, ohne einen Operator zu überschreiben, aber - was ist hier schiefgelaufen?

(. Vielen Dank allen, für Ihre Zeit)

Update: das Zeug zu geben habe ich vergessen, sind beide Sammlungen der erwartete Typ, nicht null, und beide enthalten 2 Einträge - die gleichen 2 Einträge , tatsächlich; Ich habe erwartet, dass der Gleichheitsoperator im Test wahr ist.

Update 2: Ich trennte die Null-Checks; "(object) a == null" ergibt false und setzt fort, aber "(object) b == null" erscheint als wahr zu bewerten und sendet die Ausführung an "return false" - aber wiederum die gleichen zwei Probleme bei der Ausführung kommt eigentlich nicht zurück, versucht aber, ein erstes aufzuzählen ... und b ist nicht wirklich null. Gibt es Gründe, b wäre ein gültiges Objekt, aber die Cast-Operation in (Objekt) b könnte fehlschlagen?

+0

Während des Debuggens können Sie die Maus über 'a' bewegen und den Inhalt sehen. Wenn es leer ist, ist das dein Problem. – nhouser9

+0

Wie nhouser9 sagte, überprüfen Sie, ob sie leer sind. Wenn Sie sehen, wie Ihr (Objekt) a direkt zu "false" zurückkehrt, ist es möglich, dass es null ist und nicht iteriert. – Memfisto

+0

Siehe Update - leider habe ich nicht angegeben. Beide Sammlungen haben den erwarteten Typ, nicht null und haben jeweils zwei Einträge. (Wie es passiert, sie übereinstimmen.) – Niali

Antwort

2

Wie sieht es mit Ihrer Gleichheitsprüfung aus? Nachdem Sie die Referenzgleichheit, Nullen und die Anzahl der Schlüssel überprüft haben, können Sie Except verwenden, um zu sehen, ob eines Schlüssel enthält, die nicht in dem anderen Schlüssel enthalten sind. Wenn es so ist, sind sie nicht gleich.

Nur wenn alle diese übergeben müssen Sie sehen, ob es Fälle gibt, in denen die Werte für die gleichen Schlüssel in beiden Wörterbüchern nicht übereinstimmen.

+0

Ich müsste die Werte auch in beiden Wörterbüchern testen. Die ganze Idee besteht darin, die Sammlungen auf zwei Arten zu erstellen und zu validieren, dass die Ergebnisse beider identisch sind. Ich hatte nicht daran gedacht Außer wenn. :) – Niali

+0

Das ist, was die letzte Überprüfung tut. –

0

Die Antwort war, wie immer, einfacher als ich es gemacht habe.

In Dictionary-Objektvergleichsdateien wird nicht explizit zwischen Groß- und Kleinschreibung unterschieden, und bei der Schlüsselerstellung zwischen den beiden Methoden wurde ein Fehler gefunden. Die Neudefinition von SecretAccessRuleSet-Konstruktoren zum Aufrufen des Basiskonstruktors mit StringComparer.OrdinalIgnoreCase behob das Problem.

Das Debug-Focus-Jumping-Problem ist ein Anzeigefehler, der in diesem Zusammenhang Unit-Tests verursacht; Der Code führte die markierten Zeilen nicht wirklich aus. Das machte das Ganze bizarrer als es wirklich war.

Lessons learned:

  • Beitrag alle der Code beteiligt (jemand, den Fall Problem gefangen haben würde, aber ich nahm die Einzelheiten der Schöpfung Routen für die Ausgabe außerhalb des Bereichs waren, und ich shouldn tu das nicht).

  • Blame Plugins vor dem Verdacht der Kern-IDE - die Tests, die sie unterzogen wurden, war nicht gleich.

Danke an alle.

Verwandte Themen