c# - 断言动态集合中两个不同的对象是否具有相同的值

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

在比较动态集合(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
}

此测试失败

Result Message:
Assert.Equal() Failure

Expected: List [SelectListItem { Disabled = False, Group = null, Selected = False, Text = "Foo", Value = "Bar" }]

Actual: List [SelectListItem { Disabled = False, Group = null, Selected = False, Text = "Foo", Value = "Bar" }]

对我来说,这看起来是平等的。

以防万一我测试了它是否意外地检查它是否是同一个实例。但下面的内容通过了。所以事实并非如此。

var a = new {a = "a"};
var b = new {a = "a"};
Assert.Equal(a, b); // pass

最佳答案

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

关于c# - 断言动态集合中两个不同的对象是否具有相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32863139/

相关文章:

asp.net - Azure AD 不记名 token - 获取用户标识符

具有相等项的集合中的 Java 比较器

c# - 使用 .Toarray 方法后在通用列表上排序

c# - 如何计算每对字母的字距调整?

c# - Python(到 C#)方法转换

c# - GridView SelectedIndexChanging 事件,在 TemplateField 中查找文本

c# - 测试通用类

asp.net - 跨浏览器 ASP.NET 网站开发的好资源

python - 为什么在Python中非常大的浮点值之间的比较会失败?

ActionScript:我是否应该始终使用严格相等 ("===")?