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
Проверяет, что указанные переменные объекта относятся к одному и тому же объекту.
Ответы
Ответ 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");