2016-08-11 21 views
0

私は(enum:int)AccessOptionsを持っています。これは、ユーザープリンシパル名のインデックス付きリストの単純なアクセスプロパティを反映するために辞書を設定するために使用されます。 カスタム==拡張子が空であると考えています

私はユニットテストをサポートするために必要な - 特に

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

...厄介であり、実際には基準値をチェックする辞書ジェネリックの等価演算子を呼び出す - 私は2つの異なることを確立することです必要なもの参照オブジェクトには値によって同じキーが含まれ、そのキーの関連する値はそれぞれの場合に一致します。

私は自分自身の等価演算子を書いて、私のプロジェクトで辞書オブジェクトを台無しにするのを防ぐために辞書を拡張したクラスを作成しました。このメソッドがVisual Studio 2016で単体テストのAssert.AreEqual呼び出しをデバッグするコンテキストで実行されると、いくつかのことが横向きになり、コメントを使用してそれらのマークを付けます。

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

テスト結果はAssert.AreEqual(a、b)は呼び出しがfalseを返されたが、私はどちらかのコレクションの内容が評価されたことを非常に低い信仰を持っている、と私は理由を理解していないことを示しています。

これをすべて削除し、演算子をオーバーライドしないでこれらをテストする別の方法を作成しますが、ここで何が問題になりましたか?

(おかげで、あなたの時間のために皆、。)

アップデート:私は忘れてしまったものを指定するには、両方のコレクションは、予想されるタイプの、nullで、どちらも2つのエントリ含ん - 同じ2つのエントリを実際には、私は、平等オペレータがテストで真実を返すと期待していました。

更新2:私はヌルチェックを分割しました。 "(オブジェクト)a == null"はfalseに評価され続けますが、 "(オブジェクト)b == null"がtrueに評価され、 "false false"に実行を送信するように見えますが、実際には戻りませんが、最初に列挙しようとします...そして、bは実際にはnullではありません。理由bが有効なオブジェクトであるが、(オブジェクト)bのキャスト操作が失敗する可能性がありますか?

+0

デバッグ中は、「a」の上にマウスを置いて内容を確認できます。それが空の場合、それはあなたの問題です。 – nhouser9

+0

nhouser9が言ったように、空であるかどうかを確認します。あなたの(オブジェクト)が真っ直ぐに "偽を返す"ことを見て、それはnullで反復しないかもしれません。 – Memfisto

+0

更新を見る - 申し訳ありませんが指定しませんでした。どちらのコレクションも期待される型で、nullではなく、それぞれ2つのエントリを持ちます。 (起こったとしても一致します) – Niali

答えて

2

あなたの同等性チェックはどうですか? 参照等価、ヌル、およびキーの数を確認したら、Exceptを使用して、他のキーに含まれていないキーが含まれているかどうかを確認できます。もしそうなら、彼らは平等ではありません。

両方の辞書の同じキーの値が一致しないケースがあるかどうかを確認する必要があります。

+0

私は両方の辞書の値をテストしなければならないでしょう。全体のアイデアは、2つの方法でコレクションを作成し、両方の結果が同一であることを検証することです。私は例外を使用することを考えていなかった。 :) – Niali

+0

それは最後のチェックがするものです。 –

0

答えは、いつものように私が作ったよりも簡単でした。

ディクショナリオブジェクト比較関数は、明示的に大文字小文字を区別しないため、2つのメソッド間でキーの作成に大文字小文字の不一致がありました。 SecretAccessRuleSetコンストラクタを再定義して、StringComparer.OrdinalIgnoreCaseでベースコンストラクタを呼び出して問題を修正しました。

デバッグフォーカスジャンプの問題は、このコンテキストで単体テストを苦しめることが知られている表示のバグです。コードは実際に強調表示された行を実行していませんでした。それによって、全体が実際よりも奇妙に見えるようになりました。

教訓:

  • ポスト関与するすべてのコード(誰かがケースの問題を捉えているだろうが、私は創造ルートの詳細については、問題の範囲外だったと仮定し、私はshouldnそれをしないでください)。

  • コアIDEを疑う前にプラグインを非難する - 彼らが受けたテストは同等ではありませんでした。

ありがとうございます。

関連する問題