我有一个PagedModel类,它实现IEnumerable只返回ModelData,忽略了分页数据。我还重写了Equals和GetHashCode,以允许比较两个PagedModel对象的ModelData,PageNumber,TotalPages和PageSize。
这是问题
Dim p1 As New PagedModel() With {
.PageNumber = 1,
.PageSize = 10,
.TotalPages = 10,
.ModelData = GetModelData()
}
Dim p2 As New PagedModel() With {
.PageNumber = 1,
.PageSize = 10,
.TotalPages = 10,
.ModelData = GetModelData()
}
p1.Equals(p2) =====> True
Assert.AreEqual(p1, p2) ======> False!
看起来NUnit正在调用它的内部EnumerableEqual方法来比较我的PagedModel而不是使用我提供的Equals方法!有没有办法覆盖这种行为,或者我是否必须编写自定义断言。
答案 0 :(得分:11)
做你想要的事情:我会反对它,但如果你真的不喜欢NUnit的行为并想要自定义断言,你可以提供自己的EqualityComparer。
Assert.That(p1, Is.EqualTo(p2).Using(myCustomEqualityComparer));
你应该做什么(简答):你需要GetHashCode并且等于ModelData而不是PagedModel,因为你使用PagedModel作为集合而ModelData作为元素。
你应该做什么(长答案):
您需要在ModelData上实现Equals(object),而不是覆盖PagedModel上的IEquatable<T>,其中T是IEnumerable的类型参数,并覆盖GetHashCode()。这两个方法是.Net中的所有IEnumerable方法在使用Default Equality Comparer时用来确定相等性(对于诸如Union,Distinct等操作)(你没有指定自己的IEqualityComparer)。 />
[Default Equality Comparer]检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer。否则,它返回一个EqualityComparer,它使用由T提供的Object.Equals和Object.GetHashCode的覆盖。
要正常运行,GetHashCode需要为.Equals(T)返回true的所有对象返回相同的结果。反过来不一定正确 - GetHashCode可以返回不相等的对象的冲突。 More information here - see Marc Gravel's accepted answer。我还发现在使用素数的答案中GetHashCode的实现非常有用。
答案 1 :(得分:1)
如果你看一下GIT repo中NUnit相等比较器的实现,你会看到有两个枚举的专用比较块,它具有更高的优先级(仅仅因为它放在更高的位置) )使用IEquatable<T>
界面或Object.Equals(Object)
方法comparisons,而PagedModel
类已在IEnumerable<ModelData>
类中实现或重载。
我不知道这是一个错误还是一个功能,但你可能应该首先问自己,如果你的PagedModel
类直接实现PagedModel
接口实际上是最好的选择,尤其是因为您的ModelData
不仅仅是ModelData
个实例的枚举。
通过IEnumerable<ModelData>
类的简单只读PagedModel
属性提供PagedModel
枚举可能就足够了(甚至更好)。 NUnit将停止查看您的ModelData
对象,就像在IComparer
个对象的简单枚举中一样,您的单元测试将按预期运行。
唯一的另一种选择是csauve提出的选择;为您的PagedModel
实现一个简单的自定义PagedModel
,并为所有断言提供一个实例,您将比较两个internal class PagedModelComparer : System.Collections.IComparer
{
public static readonly IComparer Instance = new PagedModelComparer();
private PagedModelComparer()
{
}
public int Compare( object x, object y )
{
return x is PagedModel && ((PagedModel)x).Equals( y );
}
}
...
[Test]
...
Assert.That( actual, Is.EqualTo( expected ).Using( PagedModelComparer.Instance ) );
...
个实例:
PagedModel
但是这会使你的测试变得比必要的更复杂,而且每当你为{{1}}编写额外的测试时,你总是要考虑使用你的特殊比较器。