2017-06-28 5 views
0

Nsubstitueオブジェクトでの.NETコレクションの使用に問題がありました。NSubstitueプロキシオブジェクトを使用したC#コレクションでのEqualsの上書き

  1. 私はこの基本クラスのための2つの正確なNsubstitueオブジェクトのプロキシを作成試験においてIに等しい(オブジェクト)を実装する基本クラスのCompareTo関数
  2. を有します。
  3. オブジェクトをコレクションに入れた後、コレクションはこれらの2つのオブジェクトプロキシが2つの異なるオブジェクトであることを示します。

私はこの動作の理由とモックアップでコレクションを定義する方法が何であるのだろうかと思います。この例ではEquals()

public class KeyTestClass : IKeyTestClass 
{ 
    public int Id { get; private set; } 

    public KeyTestClass() 
    { 
     Id = 1; 
    } 

    public override int GetHashCode() 
    { 
     return Id; 
    } 


    public int CompareTo(IKeyTestClass other) 
    { 
     return Id - other.Id; 
    } 

    public bool Equals(IKeyTestClass other) 
    { 
     return Id == other.Id; 
    } 

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


} 

public interface IKeyTestClass : IComparable<IKeyTestClass>, IEquatable<IKeyTestClass> 
{ 
    int Id { get; } 
} 

public class KeyTestClass2 : IKeyTestClass2 
{ 

} 

public interface IKeyTestClass2 
{ 

} 

[TestClass] 
public class ConsistencyRelatedTests 
{ 

    [TestMethod] 
    public void ValidateTestClass() 
    { 

     var dic = new Dictionary<IKeyTestClass,List<IKeyTestClass2>>(); 

     // using new equals function defined by Nsubstittue. 
     var item1 = Substitute.For<IKeyTestClass>(); 
     var item2 = Substitute.For<IKeyTestClass>(); 
     item1.Id.Returns(1); 
     item2.Id.Returns(1); 

     Assert.IsTrue(item1.Equals(item2)); //false, not working 
     dic.Add(item1, new List<IKeyTestClass2>()); 
     dic.Add(item2, new List<IKeyTestClass2>()); 

     // Using real class equals method 
     var item3 = new KeyTestClass(); 
     var item4 = new KeyTestClass(); 
     Assert.IsTrue(item3.Equals(item4)); //working 
     dic.Add(item3, new List<IKeyTestClass2>()); 
     dic.Add(item4, new List<IKeyTestClass2>()); 
    } 

} 
+0

モック(item1とitem2)に** Equals(IKeyTestClass other)**メソッドの設定がないので、メソッドのデフォルト値が返されます。この場合はfalseです。 –

答えて

1

KeyTestClassために実装されています。これがIKeyTestClassのすべてのインスタンスに適用されるということではありません。私たちは別のクラスKeyTestClass2 : IKeyTestClassと使用デフォルトEqualsを作成した場合、我々はまったく同じ結果を取得したい:

var item1 = new KeyTestClass2(); 
var item2 = new KeyTestClass2(); 
Assert.IsTrue(item1.Equals(item2)); // also fails, as expected 

をこれは、我々がSubstitute.For<IKeyTestClass>()を呼び出すときNSubstituteが何をするかほとんどです。これは、インターフェイスを実装する新しいクラスを作成するので、KeyTestClass.Equals実装を完全に認識しません。

ここでは、何をしようとしているかによっていくつかのオプションがあります。まず、代替を含むすべてのIKeyTestClassインスタンスを使用してKeyTestClass.Equals作品は、あなたがその罰金を使用することができます。

var item1 = new KeyTestClass(); 
var item2 = Substitute.For<IKeyTestClass>(); 
var item3 = Substitute.For<IKeyTestClass>(); 
item2.Id.Returns(1); 
item3.Id.Returns(42); 
Assert.IsTrue(item1.Equals(item2)); // Passes (as expected) 
Assert.IsFalse(item1.Equals(item3)); // Passes (as expected) 

第二に、あなたが代替にIEquatable<IKeyTestClass>.Equals方法を置き換えることができ(注:can cause problemsこと、ないObject.Equalsのため)。

var item1 = Substitute.For<IKeyTestClass>(); 
var item2 = Substitute.For<IKeyTestClass>(); 
item1.Id.Returns(1); 
item2.Id.Returns(1); 
item1.Equals(item2).Returns(true); 

Assert.IsTrue(item1.Equals(item2)); // Passes as expected 

この場合、item2.Equals(item1)をスタブアウトすることもできます。 item1.Equals(Arg.Any<IKeyTestClass>).Returns(x => KeyTestClass.Equals(item1, x.Arg<IKeyTestClass>())staticバージョンのロジックが抽出されたEqualsが必要です)で実際のロジックに委任し、この呼び出しで各代用品を構成することもできます。

また、可能であれば、実際のKeyTestClass(またはハンドコーディングされたテストダブル)を使用することを検討することもできます。すべての場合にObject.Equalsへのフォールバックのために、.NETでの均等性はややこしいことがあります。したがって、等価性が契約の重要な部分である場合には、これをスタブする必要があります。

関連する問題