使用断言来比较两个对象列表 C#

7

我目前正在学习如何使用单元测试,并且我已经创建了包含3个动物对象的实际列表和预期列表。问题是如何进行断言以检查这些列表是否相等?我尝试过CollectionAssert.AreEqual和Assert.AreEqual,但都没有成功。任何帮助将不胜感激。

测试方法:

  [TestMethod]
    public void createAnimalsTest2()
    {
        animalHandler animalHandler = new animalHandler();
        // arrange
        List<Animal> expected = new List<Animal>();
        Animal dog = new Dog("",0);
        Animal cat = new Cat("",0);
        Animal mouse = new Mouse("",0);
        expected.Add(dog);
        expected.Add(cat);
        expected.Add(mouse);
        //actual
        List<Animal> actual = animalHandler.createAnimals("","","",0,0,0);


        //assert
        //this is the line that does not evaluate as true
        Assert.Equals(expected ,actual);

    }

请查看此S.O.帖子的答案:https://dev59.com/p2435IYBdhLWcg3w0Tnc - Andrew
这个方法可行,但我无法将您的评论作为答案,感谢您的帮助,我尝试搜索答案但没有找到。 - JamesZeinzu
4个回答

14

是的,虽然这两个列表看起来相同,但它们是包含相同数据的 2 个不同对象。

如果要比较列表,应该使用CollectionAssert

CollectionAssert.AreEqual(expected, actual);

那应该就可以了。


4
CollectionAssert.AreEqual不能正常工作,它提示:CollectionAssert.AreEqual 失败。(索引为0的元素不匹配。) - JamesZeinzu
我理解这可能是因为尽管对象保存着相同的信息,但它们并不是同一个对象。是否有一种不同的方法来比较对象内容而不是对象本身? - JamesZeinzu
2
只要您使用自定义的IComparer与CollectionAssert.AreEqual一起使用,它就应该可以工作。应该是第三个参数。请参阅http://msdn.microsoft.com/de-de/library/vstudio/ms243703.aspx。 - Jesko R.

7

以防将来有人遇到这个问题,答案是我必须创建一个覆盖,如下所述的IEqualityComparer:

public class MyPersonEqualityComparer : IEqualityComparer<MyPerson>
{
public bool Equals(MyPerson x, MyPerson y)
{
    if (object.ReferenceEquals(x, y)) return true;

    if (object.ReferenceEquals(x, null)||object.ReferenceEquals(y, null)) return false;

    return x.Name == y.Name && x.Age == y.Age;
}

public int GetHashCode(MyPerson obj)
{
    if (object.ReferenceEquals(obj, null)) return 0;

    int hashCodeName = obj.Name == null ? 0 : obj.Name.GetHashCode();
    int hasCodeAge = obj.Age.GetHashCode();

    return hashCodeName ^ hasCodeAge;
}

}


1
我认为仅出于测试目的而实现IEqualityComparer(Equals()和GetHashCode())是一种代码异味。我宁愿使用以下断言方法,在其中您可以自由定义要对哪些属性进行断言:
public static void AssertListEquals<TE, TA>(Action<TE, TA> asserter, IEnumerable<TE> expected, IEnumerable<TA> actual)
{
    IList<TA> actualList = actual.ToList();
    IList<TE> expectedList = expected.ToList();

    Assert.True(
        actualList.Count == expectedList.Count,
        $"Lists have different sizes. Expected list: {expectedList.Count}, actual list: {actualList.Count}");

    for (var i = 0; i < expectedList.Count; i++)
    {
        try
        {
            asserter.Invoke(expectedList[i], actualList[i]);
        }
        catch (Exception e)
        {
            Assert.True(false, $"Assertion failed because: {e.Message}");
        }
    }
}

实际运行时,它会像下面这样:

    public void TestMethod()
    {
        //Arrange
        //...

        //Act
        //...

        //Assert
        AssertAnimals(expectedAnimals, actualAnimals);
    }

    private void AssertAnimals(IEnumerable<Animal> expectedAnimals, IEnumerable<Animal> actualAnimals)
    {
        ListAsserter.AssertListEquals(
            (e,a) => AssertAnimal(e,a),
            expectedAnimals,
            actualAnimals);
    }

    private void AssertAnimal(Animal expected, Animal actual)
    {
        Assert.Equal(expected.Name, actual.Name);
        Assert.Equal(expected.Weight, actual.Weight);
        //Additional properties to assert...
    }

我正在使用XUnit进行简单的Assert.True(...)和Assert.Equals(),但您也可以使用其他任何单元测试库。希望能对某些人有所帮助!;)


0

我修改了 AssertListEquals() 方法并使用标准的 Assert.All()。

    public static void AssertListEquals<TE, TA>(IEnumerable<TE> expected, IEnumerable<TA> actual, Action<TE, TA> asserter)
    {
        if (expected == null && actual == null) return;
        Assert.NotNull(expected);
        Assert.NotNull(actual);

        Assert.True(
            actual.Count() == expected.Count(),
            $"Lists have different sizes. Expected list: {expected.Count()}, actual list: {actual.Count()}");

        var i = 0;
        Assert.All(expected, e =>
        {
            try
            {
                asserter(e, actual.Skip(i).First());
            }
            finally
            {
                i++;
            }
        });
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接