Reputation: 13895
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.
Upvotes: 3
Views: 4247
Reputation: 27871
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).
Upvotes: 4
Reputation: 759
List<T>
equality isn't checked element to element.
Use LINQ's SequenceEqual method to check your equality.
var equal = actual.SequenceEqual(expected);
And implement IEquatable
on your object:
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;
}
}
For safety, check for nulls and what not. See Yacoub's answer for a more complete implementation.
Upvotes: 3