断言.AreEqual失败了,而它不应该失败

本文关键字:失败 不应该 AreEqual 断言 | 更新日期: 2023-09-27 18:04:26

我有一个非常奇怪的行为,我无法解释。

我有以下类:

public class Project
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

和一个返回Project对象的方法:

public Project GetByName(string Name)
{
    using (ISession session = NHibernateHelper.OpenSession())
    {
        Project project = session.CreateCriteria(typeof(Project))
                                 .Add(Restrictions.Eq("Name", Name))
                                 .UniqueResult<Project>();
        return project;
    }
}

我添加了一个单元测试来测试GetByName方法:

[TestMethod]
public void TestGetByName()
{
    IProjectsRepository projectRepository = new ProjectsRepository();
    var expected = new Project { Id = 1000, Name = "Project1" };
    var actual = projectRepository.GetByName(expected.Name);
    Assert.AreEqual<Project>(expected, actual);
}

但是当我运行单元测试时,它在比较两个对象的类型时失败,并出现以下错误:

断言。AreEqual失败了。预期:& lt; MyProject.NHibernate.Project>。实际:& lt; MyProject.NHibernate.Project>.

为什么断言失败?


不是断言。是否equal只对对象的属性进行断言?

根据文档:

断言。AreEqual方法(Object, Object)

验证两个指定的对象是否相等。如果断言失败对象不相等

断言。AreSame Method

验证指定的对象变量是否引用同一对象。

断言.AreEqual失败了,而它不应该失败

您需要重写equals方法来测试是否相等。默认情况下,它将使用引用比较,并且由于您期望的对象和实际对象位于内存中的不同位置,因此它将失败。下面是你应该尝试的:

public class Project
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public override bool Equals(Object obj) 
    {
        if (obj is Project)
        {
            var that = obj as Project;
            return this.Id == that.Id && this.Name == that.Name;
        }
        return false; 
    }
}

你也可以查看在MSDN上重写等号的指南

确保你的Project类覆盖了equals方法。当前您正在比较对象引用,并且由于您有Project的两个不同对象,您的Assert.AreEqual()将失败。

public class Project
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public override bool Equals(object o)
    {
        var result = false;
        var project = o as Project;
        if (project != null)
        {
            result = Id == project.Id;
            result &= Name.Equals(project.Name);
            return result;
        }
        return false;
    }
}

equals方法就绪后,您可以使用Assert.AreEqual

[TestMethod]
public void TestGetByName()
{
    IProjectsRepository projectRepository = new ProjectsRepository();
    var expected = new Project { Id = 1000, Name = "Project1" };
    var actual = projectRepository.GetByName(expected.Name);
    Assert.AreEqual<Project>(expected, actual);
}

PS:如果你要覆盖Equals,建议也覆盖Hashcode。

    public override int GetHashCode()
    {
        var hashcode = Id.GetHashCode();
        hashCode ^= Name.GetHashCode();
        return hashCode;
    }

AreSame vs AreEqual

Assert.AreSame仍然会失败,即使您覆盖了Equals方法。该方法实际上检查引用是否指向同一个实例。而在你的情况下,他们不会。

Assert.AreEqual将简单地检查对象是否相等,这将通过调用expected.Equals(actual)来完成。一旦您实现了override bool Equals()方法,结果将为true。

您正在比较保存相同数据的两个不同对象。您应该在Project类中重载Equals方法,并在那里实现按id进行比较。

一个简单的替代方法是:

Assert.IsTrue(string1 == string2, "Error");

如果你有一个简单的类,并且你想方便地比较它,你可以使用元组:

using System.Linq
public class Project
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}
[TestMethod]
public void TestProject()
{
    var collection1 = Project[] { new() { Id = 1, Name = "Project1" } };
    var collection2 = Project[] { new() { Id = 2, Name = "Project2" } };
    CollectionAssert.AreEqual(
       collection1.Select(p => (p.Id, p.Name)).ToArray(),
       collection2.Select(p => (p.Id, p.Name)).ToArray());
}

公认的答案是正确的,但我认为我应该添加一个非常简单的实现,适用于任何类:

public override bool Equals(object obj)
{
     return GetType().GetProperties().All(property => property.GetValue(this) == property.GetValue(obj));
}

它基本上遍历每个属性并相互检查值