4

I am currently trying to compare two lists, with the same items in it, with xUnit but getting an error while running.

Assert.Equal(expectedList, actualList);

Error:

"Assert.Equal() Failure"
Expected: List<myObject> [myObject { modifier = '+', name = "name", type = "string" }, myObject { modifier = '+', name = "age", type = "int" }]
Actual:   List<myObject> [myObject { modifier = '+', name = "name", type = "string" }, myObject { modifier = '+', name = "age", type = "int" }]

brstkr
  • 1,423
  • 3
  • 18
  • 28

1 Answers1

4

This has to do with object equality.

MyObject does not implement the Equals method. By default you get a reference equality. I assume you have two different objects for MyObject.

Meaning it does not matter that your List holds the similar object(meaning with same values) they are not of the same reference, so your test checks that, this is why it fails.

internal class MyObject
{
    {
        public char Modifier { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }

    }
}


            [Fact]
            public void ListMyObject()
            {
                var list1 = new List<MyObject>
                {
                    new MyObject{ }
                };
                var list2 = new List<MyObject>
                {
                    new MyObject{ }
                };

                Assert.Equal(list1, list2); // Fails
            }

When we update our class to this.

internal class MyObject
    {
        public char Modifier { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        //When i add this to my class.
        public override bool Equals(object obj)
        {
            return this.Name == ((MyObject)obj).Name;
        }
    }

Also as mentioned in the comments by Jonathon Chase.

It is a good idea to override the GetHashCode() method as well. It is preferred to inherit from IEquatable<T> so you can avoid casting.

Everything goes green.

        [Fact]
        public void ListMyObject()
        {
            var list1 = new List<MyObject>
            {
                new MyObject{ Name = "H" }
            };
            var list2 = new List<MyObject>
            {
                new MyObject{ Name = "H" }
            };

            Assert.Equal(list1, list2); //Passes
        }
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
panoskarajohn
  • 1,846
  • 1
  • 21
  • 37
  • 1
    Thank you so much! There was my problem, was using the default Equal method. I just have overriden it now, also added **&& this.type == ((myObject)obj).type && this.modifier == ((myObject)obj).modifier** and it works fine. – brstkr Dec 23 '19 at 16:30
  • 1
    You must also override `GetHashCode` when you override the `Equals` method for types. You should also check for type symmetry when doing equality. It's also a good idea to go ahead and implement `IEquatable` while you're at it. – Jonathon Chase Dec 23 '19 at 16:32
  • @JonathonChase i am not familiar with what you are refering. Why? -> you must also override `GetHashCode` – panoskarajohn Dec 23 '19 at 16:33
  • 1
    @panoskarajohn [Refer to this post](https://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overridden) – Jonathon Chase Dec 23 '19 at 16:34