7

I am currently trying to learn how to use unit testing, and I have created the actual list of 3 animal objects and the expected list of 3 animal objects. The question is how do I Assert to check the lists are equal? I have tried CollectionAssert.AreEqual and Assert.AreEqual but to no avail. Any help would be appreciated.

The test method:

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

    }
2

4 Answers 4

14

That is correct, as the lists might look the same, they are 2 different objects containing the same data.

In order to compare lists, you should use the CollectionAssert

CollectionAssert.AreEqual(expected, actual);

That should do the trick.

Sign up to request clarification or add additional context in comments.

3 Comments

Hmm, CollectionAssert.AreEqual doesnt work, it says: CollectionAssert.AreEqual failed. (Element at index 0 do not match.)
I understand this might be because even though the objects hold the same info, they are not the same object. Is there a different method that will compare the objects content instead of the object itself?
It should work once you use a custom IComparer along with CollectionAssert.AreEqual. Should be the third parameter. See msdn.microsoft.com/de-de/library/vstudio/ms243703.aspx
8

Just incase someone comes across this in the future, the answer was I had to create an Override, IEqualityComparer as described below:

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;
}

}

Comments

2

I am of the opinion that implementing the IEqualityComparer (Equals() and GetHashCode()) for only testing purpose is a code smell. I would rather use the following assertion method, where you can freely define that on which properties you want to do the assertions:

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}");
        }
    }
}

In action it would look like as follows:

    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...
    }

I am using XUnit for the simple Assert.True(...) and Assert.Equals(), but you can use any other unit test library for that. Hope it helps someone! ;)

Comments

0

I modified method AssertListEquals() and used standard 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++;
            }
        });
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.