I am trying to compare two Lists using
CollectionAssert.AreEqual(ListExpected, ListActual);
But I am getting an exception
Expected and actual are both <System.Collections.Generic.List`1[API.Program.Relation]> with 11 elements
Values differ at index [0]
Expected: <API.Program.Relation>
But was: <API.Program.Relation>
But when I compared the zero element using Assert.AreEqual on field by field everything was fine.
Any idea why I cannot compare using CollectionAssert
An object is "declared" equal to another object in .NET is if its Equals(object other) method returns true. You need to implement that method for your API.Program.Relation class, otherwise .NET considers your objects different unless they are reference-equal. The fact that all fields are the same does not matter to .NET: if you need field-by-field equality semantics, you need to provide an implementation of Equals that supports it.
When you override Equals, don't forget to override GetHashCode as well - these must be overriden together.
If you do not want to or cannot override Equals for some reason, you could use an overload of CollectionAssert.AreEqual that takes an instance of IComparer to assist in comparing collection elements.
Related
Out of curiosity: What comparer is used when sorting a bunch of objects using the following extension method?
OrderBy(x=> x)
Background: I have to check wether two ISet< T > instances contain the same elements and considered to use the
bool setsEqual = MySet.SequenceEqual(OtherSet);
method. As the order of those elements contained in the sets are not defined and may differ, a SequenceEqual would fail in those cases where the internal order is not the same. So i would have to explictly define an order. As the order algo for itself is completely irrelevant as long as it´s stable, i just used an "Identity" lambda expression:
bool setsEqual = MySet.OrderBy(x => x).SequenceEqual(OtherSet.OrderBy(x => x);
But what does "Compare the objects themselves" mean to the code? As this OrderBy extension method is a generic one, there must be a default compare algo in place that is able to sort objects without knowing anything more about it, and that would mean a comparison for sorting had to be delegated to the type of the set elements itself. Is there an interface that the elements´ type would have to support, or is there a default comparer (may be comparing internal memory addresses of objects) in place?
To answer the question of sorting: sorting uses IComparable<T> or IComperable if that isn't implemented. The IComperable interfaces force you to implement a int CompareTo(object) method (or int CompareTo(T) method if you used the typed version).
The order of your elements is determined by the sign of the int. The value returned is interpreted as follows:
0: the two objects are equivalent (i.e. the same)
-1: the compared object precedes this object (i.e. comes before this object)
1: the compared object follows this object (i.e. comes after this object)
The actual value is ignored, the sign is all that matters. If you implement your own IComparable interface, you have to choose the semantics for sort order.
Many objects already implement IComparable already, like all your numbers, strings, etc. You'll need to implement it explicitly if you need to sort objects you've created yourself. It's not a bad practice if you intend those objects to be displayed in a list on screen at all.
As to your specific case, where you just need to determine if a set and another IEnumerable are equivalent, then you would use the ISet<T>.SetEquals(IEnumerable<T>) method which is implemented in the standard library set implementations. Sets, by definition, only guarantee the values are unique, so as long as the number of elements are the same, you only need to detect that all the elements in one IEnumerable can be found in the set.
The method used the IComparable<T>-or the IComparable-interface depending on which of both are implemented. If none is implemented the order is arbitrary.
However you won´t need to order you instances before comparing the sets. Simply loop one set and check if all of its elements are contained in the other set. Or use this:
var areEqual = firstSet.All(x => secondSet.Contains(x)) && secondSet.All(x => firstSet.Contains(x));
Or even simpler:
var areEqual = !firstSet.Except(secondSet).Any() && !secondSet.Except(firstSet).Any();
Both ways perform much faster than your appraoch as the iteration of elements stops when the first element is found that does not fit. Using OrderBy you´d loop all elements, regardless if there was already a mismatch.
Unlike for equality, there's no 'default' comparer for objects in general.
It seems that Comparer<TKey>.Default always returns a comparer, for any type TKey. If no sensible comparison method can be determined, you get an exception, but only once the comparer is used.
At least one object must implement IComparable.
I encountered a stunning problem today where I'm trying to find if an object is contained in an List collection. The problem is that the list doesn't find the object and returns index as -1 when I can see it right there already. I then created a custom Index Finder to look for the object by comparing the properties rather than a direct equality where I discovered that one of the object's properties, a ushort array which was identical was returning false when compared, but they contain exactly the same element.
The array is as follows:
{ushort[1]} [0]13
and they're exactly the same in both except that one of the object is contained in a List while the other one is on it's own. What could be the cause of this problem? I've tried all types of different ways to get around the problem but I can't just figure out what the problem is. In this particular case what is causing the comparison between the two arrays to return false, I've tied using Object.equals as well as the normal == comparer. Thanks
For arrays, Equals will return true only if you compare two references that point to the same array. To compare different arrays by content, you can use:
Enumerable.SequenceEqual(a1, a2)
Also, if collection contains objects of your custom type, make sure that these types override Equals, equality operator(==) and GetHashCode.
I have a class, let's call it Foo, that is a value type and hence overrides the Equals/GetHashCode() methods. In a separate test fixture, I want to assert that all the properties on Foo have been set properly, not just the properties used for equality. For this reason, my test assertion specifically uses the ShouldBeEquivalentTo method, which the documentation suggests will consider two objects to be equivalent if "both object graphs have equally named properties with the same value, irrespective of the type of those objects."
However, it appears that ShouldBeEquivalentTo invokes Foo.Equals method, gets a true result and then proceeds to short-circuit the reflection based property matching that ShouldBeEquivalentTo promises.
Is this expected behavior? If so, in inspecting the FA source, I saw no easy way to alter this behavior (IEquivalencyStep is declared internal). Are there any other ways to around this?
Edit:
Dennis: Yes, the two objects I'm comparing are of the same type. To summarize, I have overridden Equals on class Foo, but do not want FA to use this notion of equality for my unit tests.
I think you cannot alter behavior of this function, it assumes that if you override Equals - than you want comparison to be the same way. You can try the following function:
dto.ShouldHave().SharedProperties().EqualTo(foo);
Or you can implement in Foo class NativeEquals method which will be calling base.Equals() , and then use this method explicitly for comparison, it will work great for value types.
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.
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."
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.
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).
according to msdn
IStructuralEquatable
Defines methods to support the comparison of objects for structural
equality. Structural equality means that two objects are equal because
they have equal values. It differs from reference equality, which
indicates that two object references are equal because they reference
the same physical object.
isnt it what Equals should do ? ( when overriding IEquatable) ?
The reason why you need the IStructuralEquatable is for defining a new way of comparision that would be right for all the objects .
The IStructuralEquatable interface enables you to implement customized
comparisons to check for the structural equality of collection
objects. That is, you can create your own definition of structural
equality and specify that this definition be used with a collection
type that accepts the IStructuralEquatable interface.
For example if you want a list that will sort all its elements by a specific definition.
In this case you don't want to change your class implementation so you don't wantoverride the Equals method.
this will define a general way to compare objects in your application.
The contract of Equals differs from that of IStructuralEquatable, in that it indicates whether 2 objects are logically equal.
By default, Equals on a reference type indicates whether two object references reference the same object instance. However, you are able to override Equals according to the logic of your application.
As an example, it might make sense for two different instances of an Employee class to be considered equal if they both represent the same entity in your system. To achieve this, employee objects with matching SSN properties would be treated as logically equal, even if they were not structurally equal.