在比较动态集合中的两个对象(ViewBag)时,我遇到了一个与xUnit.net相当奇怪的问题。
我有一个ActionFilter,使用以下方法:
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
}
中,然后分配给var a = new {a = "a"};
var b = new {a = "a"};
Assert.Equal(a, b); // pass
。
然后我有一个测试,测试我的存储库中的值是否添加到ViewBag:
SQL Antipatterns
此测试失败,
结果讯息:
Assert.Equal()失败预期:列表[SelectListItem {Disabled = False,Group = null,Selected = False,Text =“Foo”,Value =“Bar”}]
实际:列表[SelectListItem {Disabled = False,Group = null,Selected = False,Text =“Foo”,Value =“Bar”}]
对我而言看起来是平等的。
以防我测试是否意外检查它是否是同一个实例。但是下面的通过。事实并非如此。
owners
答案 0 :(得分:3)
Assert.Equal将调用对象的“Equals”方法。对于List,它只是从Object继承而来,对于引用类型,它测试实例的相等性(即同一个实例)。
相反,请尝试Enumerable.SequenceEqual(请参阅here)
更新以包括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()));