将两个List <t>与XUnit Assert函数

时间:2016-03-28 17:45:13

标签: c# assert xunit xunit.net xunit2

以下不是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 个答案:

答案 0 :(得分:4)

您只需要覆盖EqualsGetHashCode,如下所示:

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方法)。

答案 1 :(得分:2)

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

为安全起见,请检查是否有空。有关更完整的实施,请参阅Yacoub的答案。