Подтвердить что ты не робот

Assert.AreEqual терпит неудачу, пока он не должен

У меня действительно странное поведение, которое я не могу объяснить.

У меня есть следующий класс:

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;
    }
}

Я добавил Unit Test для тестирования метода 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);
}

Но когда я запускаю Unit Test, это терпит неудачу при сравнении типа двух объектов со следующей ошибкой:

Ошибка Assert.AreEqual. Ожидаемое: < MyProject.NHibernate.Project > . Фактическое:. & Л; MyProject.NHibernate.Project >

Почему утверждение не работает?


Не Assert.AreEqual, утверждающий только о свойствах объектов?

Согласно документации:

Assert.AreEqual Method (Object, Object)

Проверяет, что два указанных объекта равны. Утверждение терпит неудачу, если объекты не равны.

Метод Assert.AreSame

Проверяет, что указанные переменные объекта относятся к одному и тому же объекту.

4b9b3361

Ответ 1

Вам нужно переопределить метод 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.

Ответ 2

Убедитесь, что класс Project переопределяет метод equals. В настоящее время вы сравниваете ссылки на объекты, и поскольку у вас есть 2 разных объекта 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().

Ответ 3

Вы сравниваете два разных объекта, которые содержат одни и те же данные. Вы должны перегрузить метод Equals в вашем классе Project и реализовать сравнение по id.

Ответ 4

Легкой альтернативой было бы следующее:

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