我确定我在这里遗漏了一些简单但我无法弄清楚为什么我的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单元测试将保存的对象与检索到的对象进行比较并进行比较。我理解AreSame()会失败,因为它们不是对象的相同引用,但我希望AreEqual()通过。
如果我调试测试,我可以看到这两个对象在这些属性中似乎具有相同的值,我的测试仍然失败。有人可以告诉我为什么吗?
谢谢!
答案 0 :(得分:4)
您必须在班级上覆盖Equals()
方法。否则NUnit将使用基本实现,它比较引用(这肯定不是你在此之后)
答案 1 :(得分:1)
根据建议您需要覆盖Equals。你需要注意副作用。
你也应该覆盖GetHashCode,否则你可能会得到.Equals为真的对象,但是使用你的Id类作为字典中的键,哈希不匹配会导致多个条目带有“Equal”ID。
此外,您需要覆盖==和!=运算符以保持一致的行为。
想象一下如果.Equals是真的但是==是错误的混淆。
答案 2 :(得分:0)
你做需要像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“代理”的对象与另一个尚未进行“对象”的对象之间进行了相等检查,则由于类型不匹配而导致失败。解决方案(由S#arp Architecture project提供)是将类型测试修改为:
public override bool Equals(object obj) {
...
if (GetType() != obj.GetTypeUnproxied())
{
return false;
}
...
}
protected virtual Type GetTypeUnproxied() { return GetType(); }
这有效地返回所有情况下底层对象的类型,即使compareTo对象是NHib代理也是如此。
Equals方法可能非常棘手,因为正确的方法很重要,因此理想情况下,您可以将其分解为某种Layer Supertype(Fowler)。许多开源项目,包括我之前提到的S#arp,提供了如何执行此操作的示例。
HTH,
Berryl