【问题标题】:Why Assert.AreEqual<T> fails with identical objects?为什么 Assert.AreEqual<T> 使用相同的对象失败?
【发布时间】:2013-11-19 13:31:10
【问题描述】:

我有一个包含这个属性的类:

public class Person
{
    public long Id { get; set; }

    public string Name { get; set; }

    public int? IdCountry { get; set; }
    public virtual Country Country { get; set; }
    public int? IdState { get; set; }
    public virtual State State { get; set; }
}

public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class State
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int IdCountry { get; set; }
    public virtual Country Country { get; set; }
}

在单元测试中,我创建了 2 个具有相同值的对象

Person expected = new Person()
{
    Name = "blablablbla",
    Id = 1
};
Person actual = PessoaFactory.Create(Name: "blablablbla", Id: 1);
Assert.AreEqual<Person>(expected, actual);

但是 Assert.AreEqual 会抛出异常。

【问题讨论】:

  • 因为 Object.Equals() (最终会被调用)会比较引用(你有类,而不是结构),显然它们是两个不同的对象(两个实例)。 重写它,如果您想在 Person 之间实现某种比较(什么样的比较...这取决于。仅 ID?所有字段?由您决定)。

标签: c# assert


【解决方案1】:

您需要覆盖Equals 来比较对象。默认实现比较引用,而不是值。请参阅MSDN documentation

【讨论】:

    【解决方案2】:

    因为你需要覆盖EqualsGetHashCode

    public override bool Equals(object o)
    {
        if (!(o is Person)) { return false; }
        return ((Person)o).Id == this.Id;
    }
    
    public override int GetHashCode()
    {
        return this.Id;
    }
    

    Assert.AreEqual&lt;T&gt; 使用该类型的默认比较器。该类型的默认比较器是比较哈希码。哈希码不相等。

    【讨论】:

    • ...和GetHashCode()。我们尽可能宣传最佳实践。
    • 您还需要覆盖GetHashCode()
    • @RuiJarimba,你实际上没有override GetHashCode 方法;但这是一个很好的做法,所以我进行了修改。但让我们明确一点,它没有必须去做。
    • 如果 OP 正在比较 multiple 属性,而不仅仅是 ID,则在这两个检查中都需要考虑这些属性 - 否则 new Person { Id = 1, Name = "Person1" }; new Person { Id = 1, Name = "Person2" } 将相等(当OP可能不希望他们成为)。
    • @MichaelPerrenoud 当然,而且 OP 并没有真正提到他们正在比较的只是 ID 还是字段级别的比较,所以认为值得澄清。
    【解决方案3】:

    因为它比较的是引用而不是其中的实际值。

    【讨论】:

      【解决方案4】:

      您有两个不同的对象引用要比较。

      例如使用Assert.IsTrue(expected.Id == actual.Id) 或覆盖Equals 和GetHashCode 以便能够比较您的对象

      【讨论】:

        【解决方案5】:

        默认情况下,.Net 框架本身不处理深度平等合作,如果您没有覆盖该方法,Assert.AreEqual 会在 object.Equals 对象上调用 Equals 方法。 Object.Equals 仅实施参考检查。您应该实现自己的 Equals 方法,例如:

        public override bool Equals(object o)
        {
            var cast = o as Person;
            if (cast == null) 
                return false; 
            return cast.Id == this.Id;
        }
        
        public override int GetHashCode()
        {
            return this.Id;
        }
        

        更多信息可以查看MSDN Doc

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-25
          • 1970-01-01
          • 1970-01-01
          • 2018-08-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-13
          相关资源
          最近更新 更多