2017-06-28 28 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,所以当平等是合同的关键部分时,需要小心谨慎。