Сравнение двух List<T> с функцией XUnit Assert
Следующее не утверждает true с XUnit (StartDate и EndDate являются единственными двумя открытыми свойствами DatePeriod):
var actual = new List<DatePeriod>()
{
new DatePeriod() { StartDate = new DateTime(2017, 1, 20), EndDate = new DateTime(2018, 1, 19)},
new DatePeriod() { StartDate = new DateTime(2018, 1, 20), EndDate = new DateTime(2018, 3, 31)}
};
var expected = new List<DatePeriod>()
{
new DatePeriod() { StartDate = new DateTime(2017, 1, 20), EndDate = new DateTime(2018, 1, 19)},
new DatePeriod() { StartDate = new DateTime(2018, 1, 20), EndDate = new DateTime(2018, 3, 31)}
};
Assert.Equal(actual, expected);
Основываясь на некоторых исследованиях, я ожидал, что в последней версии XUnit они в конечном итоге будут считаться равными, поскольку при использовании Assert, если порядок такой же, как и у него.
2 ответа
Вам просто нужно переопределить Equals
а также GetHashCode
как это:
public class DatePeriod
{
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
DatePeriod other = (DatePeriod)obj;
return StartDate.Equals(other.StartDate) && EndDate.Equals(other.EndDate);
}
public override int GetHashCode()
{
return new {StartDate, EndDate}.GetHashCode();
}
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
xUnit распознает коллекции в том смысле, что вы можете вызвать Assert.Equal
в то время как другие платформы тестирования требуют специальных методов, таких как CollectionAssert.AreEqual
,
Во всех случаях структура будет вызывать Equals
для каждого элемента в списке, передавая соответствующий элемент из другого списка. Если у вас есть список строк или целых чисел, то Equals
правильно реализовано по умолчанию. Для пользовательских объектов, таких как DatePeriod
реализация по умолчанию Equals
Метод основан на ссылочном равенстве, т. е. два объекта равны, если они фактически являются одним и тем же объектом. Чтобы получить равенство на основе значений, вы должны переопределить Equals
метод (а также GetHashCode
метод в соответствии с рекомендациями).
List<T>
равенство не проверяется элемент за элементом.
Используйте метод LINQ SequenceEqual, чтобы проверить ваше равенство.
var equal = actual.SequenceEqual(expected);
И реализовать IEquatable
на вашем объекте:
public class DatePeriod : IEquatable<DatePeriod>
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool Equals(Period other)
{
return StartDate == other.StartDate && EndDate == other.EndDate;
}
}
Для безопасности проверьте на нули, а что нет. Смотрите ответ Якуба для более полной реализации.