Unit testing NUnit AreEqual总是返回false

Unit testing NUnit AreEqual总是返回false,unit-testing,nhibernate,nunit,Unit Testing,Nhibernate,Nunit,我确信我遗漏了一些简单的东西,但我不明白为什么我的NUnit对象比较测试继续失败 我有一个简单的目标: public virtual int Id { get; private set; } public virtual string Description { get; set; } public virtual string Address { get; set; } public virtual string Ports { get; set; }

我确信我遗漏了一些简单的东西,但我不明白为什么我的NUnit对象比较测试继续失败

我有一个简单的目标:

 public virtual int Id { get; private set; }

    public virtual string Description { get; set; }

    public virtual string Address { get; set; }

    public virtual string Ports { get; set; }

    public virtual string Password { get; set; }        

    public virtual ServerGroup ServerGroup { get; set; }
我将这个对象的一个实例持久化到我的数据库中,然后使用NHibernate将其取出。我的NUnit单元测试将保存的对象与检索到的对象进行比较,并对它们进行比较。我知道Areame()会失败,因为它们不是对对象的相同引用,但我希望AreEqual()会通过

如果我调试测试,我可以看到这两个对象在这些属性中似乎具有相同的值,我的测试仍然失败。有人能告诉我为什么吗


谢谢

您必须重写类上的
Equals()
方法。否则,NUnit将使用基本实现,它比较引用(这里肯定不是您要讨论的内容)

您必须在类上重写
Equals()
方法。否则NUnit将使用基本实现,它比较引用(这肯定不是您在这里要讨论的内容)

您确实需要按照Grzenio的建议覆盖Equals,但请注意NHibernate可能出现的微妙混淆源。具体来说,当启用延迟加载时,类型比较测试可能会失败。为了说明这一点,这里有一个写得很好的Equals方法:

    // override object.Equals
    public override bool Equals(object obj)
    {
        //       
        // See the full list of guidelines at
        //   http://go.microsoft.com/fwlink/?LinkID=85237  
        // and also the guidance for operator== at
        //   http://go.microsoft.com/fwlink/?LinkId=85238
        //

        if (GetType() != obj.GetType())
        {
            return false;
        }
        ....
    }
但当启用延迟加载时,NHib的工作方式是生成实际对象的代理(从而延迟不必要的数据库命中)。如果在一个已被NHib“代理”的对象和另一个未被“代理”的对象之间进行相等性检查,它将由于类型不匹配而失败。解决方案(由提供)是将型式试验修改为如下:

public override bool Equals(object obj) {
    ...
    if (GetType() != obj.GetTypeUnproxied())
    {
        return false;
    }
       ...
 }

protected virtual Type GetTypeUnproxied() { return GetType(); }
在所有情况下,即使compareTo对象是NHib代理,也可以有效地返回基础对象的类型

Equals方法可能很棘手,因为正确的方法很重要,因此理想情况下,您可以将其考虑到某种层超类型(Fowler)中。许多开源项目,包括我前面提到的S#arp项目,都提供了如何做到这一点的示例

HTH,
Berryl

您确实需要按照Grzenio的建议重写Equals,但要注意NHibernate可能会出现的微妙混淆源。特别是,当启用延迟加载时,类型比较测试可能会失败。为了说明这一点,这里有一个编写良好的Equals方法:

    // override object.Equals
    public override bool Equals(object obj)
    {
        //       
        // See the full list of guidelines at
        //   http://go.microsoft.com/fwlink/?LinkID=85237  
        // and also the guidance for operator== at
        //   http://go.microsoft.com/fwlink/?LinkId=85238
        //

        if (GetType() != obj.GetType())
        {
            return false;
        }
        ....
    }
但是,当启用延迟加载时,NHib的工作方式是生成实际对象的代理(从而推迟不必要的数据库命中)。如果在一个已由NHib“代理”的对象和另一个未被“代理”的对象之间进行相等性检查,它将因类型不匹配而失败。解决方案(由提供,将型式试验修改为如下内容:

public override bool Equals(object obj) {
    ...
    if (GetType() != obj.GetTypeUnproxied())
    {
        return false;
    }
       ...
 }

protected virtual Type GetTypeUnproxied() { return GetType(); }
在所有情况下,即使compareTo对象是NHib代理,也可以有效地返回基础对象的类型

Equals方法可能很棘手,因为正确的方法很重要,因此理想情况下,您可以将其考虑到某种层超类型(Fowler)中。许多开源项目,包括我前面提到的S#arp项目,都提供了如何做到这一点的示例

HTH,

Berryl

正如建议的那样,您需要覆盖Equals。您确实需要了解其副作用

您还应该重写GetHashCode,否则您可能会得到.Equals为true的对象,但使用Id类作为字典中的键,哈希将不匹配,从而导致多个Id为“Equal”的条目

此外,您还需要重写==和!=运算符以保持一致的行为


想象一下,如果.Equals为真,而==为假,会出现混乱。

正如建议的那样,您需要覆盖Equals。您确实需要注意其副作用

您还应该重写GetHashCode,否则您可能会得到.Equals为true的对象,但使用Id类作为字典中的键,哈希将不匹配,从而导致多个Id为“Equal”的条目

此外,您还需要重写==和!=运算符以保持一致的行为

想象一下,如果.Equals为真,但是==为假,那么会出现混乱。

这也可能是重复的:这也可能是重复的: