C# 使用SequenceEqual与包含时间跨度的比较列表进行Moq单元测试

C# 使用SequenceEqual与包含时间跨度的比较列表进行Moq单元测试,c#,unit-testing,C#,Unit Testing,我有一个简单的单元测试方法,比较包含TimeSpan值的两个列表,我们还使用Moq初始化测试: private IRepository _RepositoryTimeBand; [TestInitialize] public void TestInit() { var TimeBandSet = new List<TimeBand> { new TimeB

我有一个简单的单元测试方法,比较包含TimeSpan值的两个列表,我们还使用Moq初始化测试:

       private IRepository _RepositoryTimeBand;

       [TestInitialize]
       public void TestInit()
       {
        var TimeBandSet = new List<TimeBand>
            {
                new TimeBand() {StartTime = new TimeSpan(7, 30, 0), EndTime = new TimeSpan(16, 0, 0)},
                new TimeBand() {StartTime = new TimeSpan(19, 0, 0), EndTime = new TimeSpan(21, 0, 0)}
            };

        var RepositoryMoq = new Mock<IRepository>();

        RepositoryMoq.Setup(
            mr =>
            mr.GetTimeBand().Returns(TimeBandSet);

        _RepositoryTimeBand = RepositoryMoq.Object;


       [TestMethod]
    public void GetTimeBand_ExpectListOfTimeBandReturned()
    {
        var expected = new List<TimeBand>
            {
                new TimeBand {StartTime = new TimeSpan(7, 30, 0), EndTime = new TimeSpan(16, 0, 0)},
                new TimeBand {StartTime = new TimeSpan(19, 0, 0), EndTime = new TimeSpan(21, 0, 0)}
            };

        var timeBandList = _RepositoryTimeBand.GetTimeBand();

        Assert.IsNotNull(timeBandList);
        Assert.IsTrue(timeBandList.SequenceEqual(expected));
    }
Assert.IsTrue(timeBandList.SequenceEqual(预期))始终返回false,即使两个列表是
相同,
SequenceEqual
是比较两个列表的正确方法吗?如果没有,还有其他方法比较这些列表吗


多亏了我们可以使用SequenceEqual通过实现EqualityComparer来比较时间段集

CollectionAssert给出了一个更好的信息(表示第一个不同的项目),但IComparer比EqualityComparer更混乱(在我给出的示例中,我给出了-1 lhs比rhs“大”还是“小”;这是不正确的,但因为我们真正关心的是它们是否相同,这就足够了。(不过,无可否认,为复杂对象引入一个有用的哈希函数也可能是乏味的)

需要记住的重要一点是,除非目标(在本例中为TimeBand)实现IComparable或重写==/equals成员,否则比较将在引用上进行,因此具有相同值的两个不同对象列表将显示为不同,除非使用某种帮助器来比较它们

[TestClass]
public class ComparingTimespans {

    [TestMethod]
    public void CompareTimeBandTwoListsAreSameUsingCollectionAssert() {

var lhs = new List<TimeBand>
{
    new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
          new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
      };

var rhs = new List<TimeBand>
{
    new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
    new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
      };


CollectionAssert.AreEqual(lhs, rhs, new TimeBandComparer());

}

[TestMethod]
public void CompareTimeBandTwoListsAreSameUsingSequenceEquals() {

    var lhs = new List<TimeBand>
    {
new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
    };

    var rhs = new List<TimeBand>
    {
 new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
 new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
    };

    Assert.IsTrue(lhs.SequenceEqual(rhs, new TimebandEqualityComparer()));

}


private class TimeBand {
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }
}

private class TimeBandComparer : IComparer {

   public int Compare(object x, object y) {
var xTb = x as TimeBand;
var yTb = y as TimeBand;
return (xTb.StartTime == yTb.StartTime && xTb.EndTime == yTb.EndTime)
         ? 0
         : -1;
   }
}

private class TimebandEqualityComparer : IEqualityComparer<TimeBand> {
    public bool Equals(TimeBand x, TimeBand y) {
return x.StartTime == y.StartTime && x.EndTime == y.EndTime;
    }

    public int GetHashCode(TimeBand obj) {
return obj.StartTime.GetHashCode() ^ obj.EndTime.GetHashCode();
    }
}
[TestClass]
公共类比较时间跨度{
[测试方法]
public void comparetimebandtowlistsaresameusing collectionassert(){
var lhs=新列表
{
新时区{StartTime=new TimeSpan(1,1,1),EndTime=new TimeSpan(2,2,2)},
新时区{StartTime=newtimespan(3,3,3),EndTime=newtimespan(4,4,4)},
};
var rhs=新列表
{
新时区{StartTime=new TimeSpan(1,1,1),EndTime=new TimeSpan(2,2,2)},
新时区{StartTime=newtimespan(3,3,3),EndTime=newtimespan(4,4,4)},
};
AreEqual(lhs、rhs、新的TimeBandComparer());
}
[测试方法]
public void CompareTimeBandTwoListsAreSameUsingSequenceEquals(){
var lhs=新列表
{
新时区{StartTime=new TimeSpan(1,1,1),EndTime=new TimeSpan(2,2,2)},
新时区{StartTime=newtimespan(3,3,3),EndTime=newtimespan(4,4,4)},
};
var rhs=新列表
{
新时区{StartTime=new TimeSpan(1,1,1),EndTime=new TimeSpan(2,2,2)},
新时区{StartTime=newtimespan(3,3,3),EndTime=newtimespan(4,4,4)},
};
Assert.IsTrue(lhs.SequenceEqual(rhs,新的TimebandEqualityComparer());
}
私人类时区{
公共时间跨度开始时间{get;set;}
公共时间跨度结束时间{get;set;}
}
专用类时区比较器:IComparer{
公共整数比较(对象x、对象y){
var xTb=x作为时间段;
var yTb=y作为时间段;
返回(xTb.StartTime==yTb.StartTime&&xTb.EndTime==yTb.EndTime)
? 0
: -1;
}
}
私有类TimebandEqualityComparer:IEqualityComparer{
公共布尔等于(时间带x、时间带y){
返回x.StartTime==y.StartTime&&x.EndTime==y.EndTime;
}
公共整数GetHashCode(时区obj){
返回obj.StartTime.GetHashCode()^obj.EndTime.GetHashCode();
}
}

}

使用Microsoft的测试框架执行
imeband
或覆盖
Equals()
。让我重新表述一下:尝试运行此代码:
如果(新时区{StartTime=new TimeSpan(7,30,0),EndTime=new TimeSpan(16,0,0)}。等于(新时区{StartTime=new TimeSpan(7,30,0),EndTime=new TimeSpan(16,0,0)}{Console.writeLink(“耶!对象可以比较”)}
你能显示
TimeBand
类的代码吗?我想这就是隐藏问题的地方:)我已经用TimeBand类更新了问题。你的
IComparer
完全坏了。
Compare(a,b)=-1
Compare(b,a)==-1
=>违反合同。=>未定义的行为|只是使用一些任意排序,但不是不一致的排序。谢谢。尝试了TimebandEqualityComparer,它似乎工作正常。@CodesInChaos是的。确实提到过。它只用于比较,而不是排序,对提出排序方案没有足够的兴趣。U通常,我会使用相等比较器。
private class TimebandEqualityComparer : IEqualityComparer<TimeBand>
private class TimeBandComparer : IComparer
[TestClass]
public class ComparingTimespans {

    [TestMethod]
    public void CompareTimeBandTwoListsAreSameUsingCollectionAssert() {

var lhs = new List<TimeBand>
{
    new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
          new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
      };

var rhs = new List<TimeBand>
{
    new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
    new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
      };


CollectionAssert.AreEqual(lhs, rhs, new TimeBandComparer());

}

[TestMethod]
public void CompareTimeBandTwoListsAreSameUsingSequenceEquals() {

    var lhs = new List<TimeBand>
    {
new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
    };

    var rhs = new List<TimeBand>
    {
 new TimeBand { StartTime = new TimeSpan(1,1,1) , EndTime = new TimeSpan(2,2,2)},
 new TimeBand { StartTime = new TimeSpan(3,3,3) , EndTime = new TimeSpan(4,4,4)},
    };

    Assert.IsTrue(lhs.SequenceEqual(rhs, new TimebandEqualityComparer()));

}


private class TimeBand {
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }
}

private class TimeBandComparer : IComparer {

   public int Compare(object x, object y) {
var xTb = x as TimeBand;
var yTb = y as TimeBand;
return (xTb.StartTime == yTb.StartTime && xTb.EndTime == yTb.EndTime)
         ? 0
         : -1;
   }
}

private class TimebandEqualityComparer : IEqualityComparer<TimeBand> {
    public bool Equals(TimeBand x, TimeBand y) {
return x.StartTime == y.StartTime && x.EndTime == y.EndTime;
    }

    public int GetHashCode(TimeBand obj) {
return obj.StartTime.GetHashCode() ^ obj.EndTime.GetHashCode();
    }
}