如果两个不同的对象在动态集合中具有相同的值,则置位

时间:2015-09-30 09:57:13

标签: c# asp.net equality viewbag xunit.net

在比较动态集合中的两个对象(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

1 个答案:

答案 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()));