The following is not asserting to true with XUnit (StartDate and EndDate are the only two public properties of 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);
Based on some research I expected in the latest version of XUnit that these would end up being considered equal since when using Assert as long as the order is the same which it is.
You simply need to override Equals
and GetHashCode
like this:
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 recognizes collections in the sense that you can call Assert.Equal
while other testing frameworks require special methods like CollectionAssert.AreEqual
.
In all cases, the framework would invoke Equals
for each item in the list passing the corresponding item from the other list. If you have a list of strings or integers then Equals
is correctly implemented by default. For custom objects like DatePeriod
, the default implementation of the Equals
method is based on reference equality, i.e., two objects are equal is they are actually the same object. To get value based equality, you have to override the Equals
method (and also GetHashCode
method as recommended).