2017-06-28 64 views
0

我有一個與Nsubstitue對象一起使用.NET集合的問題。與NSubstitue代理對象覆蓋的C#集合等於

  1. 我有一個基類,其中我實現equals(對象),的CompareTo函數
  2. 在測試I創建此基類中的兩個精確Nsubstitue對象代理。
  3. 將對象放入集合後,集合顯示這兩個對象代理是兩個不同的對象。

我不知道可能是什麼原因導致了這種行爲,以及如何用模型定義集合。

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

我的直覺是,因爲沒有對mocks(item1和item2)上的** Equals(IKeyTestClass other)**方法進行設置,它將返回方法的默認值,在這種情況下,該方法爲false 。 –

回答

1

在這個例子中Equals()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的實現。

這裏有幾個選項,這取決於你想要做什麼。首先,你的作品KeyTestClass.Equals所有IKeyTestClass實例,包括替代品,所以你可以使用罰款:

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方法(注意:不是Object.Equals,該can cause problems)。

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>())(需要提取Equals版本的Equals邏輯)將實際邏輯委託給此實體,並使用此調用配置每個替代實體。

另一個可以考慮的選擇是在這裏使用真實的KeyTestClass(如果可能的話)(或手工編碼的測試雙)。在.NET中,平等可能會有點棘手,因爲所有事情都可以回到Object.Equals,所以當平等是合同的關鍵部分時,需要小心謹慎。