Rvd*_*vdK 2 c# collections comparison nunit assert
我正在尝试比较包含自定义对象的 2 个列表(包装在一个对象中)。我不关心顺序,但是如果列表 1 包含“1,2,3,4”,那么列表 2 必须并且只包含这些元素。例如:“4,2,3,1”
基于比较两个 List<T> 对象的相等性,忽略顺序 ignoring-order 我使用了 except 和 Any 但它没有给我想要的结果。
如果我使用Assert.Equals它失败,但Assert.IsTry(list1.equals(list2))成功。
此外,如果我删除 Equals 和 GetHashCode 实现,则两个测试都会失败。
public class AppointmentCollection : List<Appointment>
{
public override bool Equals(object obj)
{
var appCol = obj as AppointmentCollection;
if (appCol == null)
{
return false;
}
return (appCol.Count == this.Count) && !(this.Except(appCol).Any());
}
public override int GetHashCode()
{
unchecked
{
//use 2 primes
int hash = 17;
foreach (var appointment in this)
{
hash = hash * 19 + appointment.GetHashCode();
}
return hash;
}
}
}
public class Appointment
{
public string Title {get; set;}
public DateTime StartTime {get; set;}
public DateTime EndTime { get; set;}
public override bool Equals(object obj)
{
var appointment = obj as Appointment;
if (appointment == null)
{
return false;
}
return Title.Equals(appointment.Title) &&
StartTime.Equals(appointment.StartTime) &&
EndTime.Equals(appointment.EndTime);
}
public override int GetHashCode()
{
unchecked
{
//use 2 primes
int hash = 17;
hash = hash * 19 + Title.GetHashCode();
hash = hash * 19 + StartTime.GetHashCode();
hash = hash * 19 + EndTime.GetHashCode();
return hash;
}
}
}
[Test]
public void TestAppointmentListComparisonDifferentOrder()
{
var appointment1 = new Appointment(
"equals test1",
new DateTime(2013, 9, 4),
new DateTime(2013, 9, 4));
var appointment2 = new Appointment(
"equals test2",
new DateTime(2013, 9, 4),
new DateTime(2013, 9, 4));
var list1 = new AppointmentCollection() { appointment1, appointment2 };
var list2 = new AppointmentCollection() { appointment2, appointment1 };
//With Equals/GetHashCode in AppointmentCollection implemented
CollectionAssert.AreEqual(list1, list2); //fails
Assert.IsTrue(list1.Equals(list2)); //success
//Without Equals/GetHashCode in AppointmentCollection implemented
CollectionAssert.AreEqual(list1, list2); //fails
Assert.IsTrue(list1.Equals(list2)); //fails
}
Run Code Online (Sandbox Code Playgroud)
您没有明确说明您使用的是哪种单元测试工具。也许CollectionAssert是 class Microsoft.VisualStudio.TestTools.UnitTesting.CollectionAssert,也许是NUnit.Framework.CollectionAssert,或者别的什么?
因此,请检查您的测试工具的文档,或在此处写下您使用的工具。
然而,常见的是
CollectionAssert.AreEqual( ... );
Run Code Online (Sandbox Code Playgroud)
检查集合是否以相同的顺序相同,而
CollectionAssert.AreEquivalent( ... );
Run Code Online (Sandbox Code Playgroud)
会检查你想要什么。所以使用后者。
这两种方法CollectionAssert实际上都没有使用您对Equals(object). 要使用它,请编写:
Assert.AreEqual( ... );
Run Code Online (Sandbox Code Playgroud)
编辑:我认为Assert.AreEqual(exp, act);最终总是exp.Equals(act)会在AppointmentCollection. 但事实证明,我们以私有实例方法EqualConstraint.ObjectsEqual结束,正如人们所见,它会检查运行时类型是否实现,ICollection在这种情况下,您的覆盖从未被使用。
经验教训:使用Assert.AreEqual可能会与集合混淆。使用CollectionAssert.AreEquivalent或CollectionAssert.AreEqual来明确您的意图。如果您只需要它进行测试Equals,AppointmentCollection则不必覆盖。如果您需要应用程序本身并希望对其进行测试,请按list1.Equals(list2)字面意思编写测试以确保您自己的覆盖是经过测试的内容。
(在任何情况下Appointment,当然都需要覆盖。)