[英]Why are hashcodes different when two objects of the same type have the same values?
[英]Assert if two different objects have same values in a dynamic collection
在比较动态集合(ViewBag)中的两个对象时,xUnit.net遇到了一个相当奇怪的问题。
我有一个具有以下方法的ActionFilter:
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var selectList = new List<SelectListItem>();
var foos = _repo.Get();
foreach (var foo in foos)
{
var selectItem = new SelectListItem()
{
Text = foo.Text,
Value = foo.Value
};
selectList.Add(selectItem);
}
filterContext.Controller.ViewBag.SelectList = selectList;
}
请注意如何将值包装在List<SelectListItem>
,然后将其分配给ViewBag
。
然后,我进行了一个测试,测试是否将存储库中的值添加到ViewBag中:
public void MyTest()
{
// Arrange
var fakeController = Substitute.For<Controller>();
var fakeContext = Substitute.For<ActionExecutingContext>();
fakeContext.Controller = fakeController;
var repository = Substitute.For<IRepository<Foo>>();
var foo = new Foo() {Text = "Foo", Value = "Bar"};
var foos = new List<Foo> { foo };
repository.Get().Returns(foos);
var filter = new MyFilter(repository);
// Act
filter.OnActionExecuting(fakeContext);
// Assert
var expected = new List<SelectListItem> {new SelectListItem {Text = foo.Text, Value = foo.Value}};
Assert.Equal(expected, fakeContext.Controller.ViewBag.SelectList); // fails
}
该测试失败,并
结果消息:
Assert.Equal()失败预期值:列表[SelectListItem {Disabled = False,Group = null,Selected = False,Text =“ Foo”,Value =“ Bar”}]
实际:列表[SelectListItem {禁用= False,组= null,已选择= False,文本=“ Foo”,值=“ Bar”}]
在我看来,这是平等的。
以防万一,我测试了是否意外检查了是否是同一实例。 但是下面通过了。 事实并非如此。
var a = new {a = "a"};
var b = new {a = "a"};
Assert.Equal(a, b); // pass
Assert.Equal将调用对象的“ Equals”方法。 对于List,它只是从Object继承而来,对于Object,引用类型将测试实例是否相等(即同一实例)。
相反,请尝试Enumerable.SequenceEqual(请参阅此处 )
更新以包括EqualityComparer的实现:
// Custom comparer for the SelectListItem class
class SelectListItemComparer : IEqualityComparer<SelectListItem>
{
// Products are equal if their names and product numbers are equal.
public bool Equals(SelectListItem x, SelectListItem y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the products' properties are equal.
return x.Text.Equals(y.Text) && x.Value.Equals(y.Value);
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(SelectListItem item)
{
//Check whether the object is null
if (Object.ReferenceEquals(item, null)) return 0;
//Get hash code for the Name field if it is not null.
int hashText = item.Text == null ? 0 : item.Text.GetHashCode();
//Get hash code for the Code field.
int hashValue = item.Value.GetHashCode();
//Calculate the hash code for the product.
return hashText ^ hashValue;
}
}
然后我们可以做:
// Assert
var expected = new List<SelectListItem> {new SelectListItem {Text = "this", Value = "that"}};
var actual = new List<SelectListItem> {new SelectListItem {Text = "this", Value = "that"}};
Assert.IsTrue(expected.SequenceEqual(actual, new SelectListItemComparer()));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.