Reputation: 1409
I have a class MyCustomClass:
public MyCustomClass
{
public MyCustomClass()
{
MyObject = new List<MyCustomObject>();
}
public List<MyCustomObject> MyObject {get; set;}
}
In the Test:
List<MyCustomObject> aux = new List<MyCustomObject>();
MyCustomClass oClass = new MyCustomClass();
Assert.AreEqual(aux, oClass.MyObject)
The test has failed, why? Every property, static member, etc are the same.
Upvotes: 10
Views: 8498
Reputation: 22297
I decompiled Assert.AreEqual
(which is in the Microsoft.VisualStudio.QualityTools.UnitTestFramework
GAC assembly) using dotPeek and found that Assert.AreEqual(aux, oClass.MyObject)
will ultimately result in the following call where aux
is expected
and oClass.MyObject
is actual
:
object.Equals((object) expected, (object) actual)
From the documentation for the static object.Equals(Object, Object)
we read:
The static Equals(Object, Object) method indicates whether two objects, objA and objB, are equal. It also enables you to test objects whose value is null for equality. It compares objA and objB for equality as follows:
It determines whether the two objects represent the same object reference. If they do, the method returns true. This test is equivalent to calling the ReferenceEquals method. In addition, if both objA and objB are null, the method returns true.
It determines whether either objA or objB is null. If so, it returns false.
If the two objects do not represent the same object reference and neither is null, it calls objA.Equals(objB) and returns the result. This means that if objA overrides the Object.Equals(Object) method, this override is called.
Now, List<T>
is known to be a reference type, and we know that neither of the two lists you are comparing are null, so the final comparison between your two objects will be
expected.Equals(actual)
Since List<T>
does not override Equals
, it uses the base object implementation, which performs reference comparison, and thus fails (expected
and actual
were "newed" separately).
What you want is structural comparison, i.e. the pair-wise equality of the elements in your lists. See @ReedCopsey answer for the correct assertion for that (CollectionAssert.AreEqual
).
Upvotes: 0
Reputation: 164291
As already answered, two lists of same type with zero elements are not considered equal.
The reason behind this, is that AreEqual
actually calls aux.AreEqual(oClass.MyObject)
, using the objects own equality implementation. Because this is not overridden for List<T>
, it falls back to the implementation in Object
, which is a simple reference equality check. Those two lists are clearly not the same reference, and therefore, they are not considered equal.
Because the Equals
method exists and is virtual on Object
, your own classes can override Equals
in order to provide another concept for equality than reference equality. This is done on objects like String
, which compare equal even for different references, if the data is the same.
Upvotes: 4
Reputation: 564433
In this case Assert.AreEqual
will check to see if the two objects are the same, and they're not. You should use CollectionAssert.AreEqual
instead, which will return true if the two "have the same elements in the same order and quantity."
Upvotes: 19