CollectionAssert.Contains(myList, myItem) != Assert.IsTrue(myList.Contains(myItem))

16,566

Solution 1

Looking at the code for CollectionAssert.Contains(), the actual comparison is done by iterating the collection, and comparing each element to the target elements with object.Equals(current, target).

So the answer to your question is that if you haven't overridden the object version of Equals() so that it dispatches to your IEquatable<T> version, you should. Otherwise the test is going to fail if reference equality isn't satisfied, since the IEquatable<T> overload of Equals() doesn't override the overload inherited from object.

Solution 2

It seems CollectionAssert.Contains is not looking at your object's member values, but is comparing instances' memory address. The following example's CollectionAssert will fail, due to the fact that, although they have the same member values, obj and obj2 are not the same instance object;

        MyType obj = new MyType { prop1 = "foo", prop2 = "bar" };
        MyType obj2 = new MyType { prop1 = "foo", prop2 = "bar" };

        List<MyType> lstObj = new List<MyType> { obj2 };

        CollectionAssert.Contains(lstObj, obj);

That being said, the following example's CollectionAssert will succeed because it will be searching for obj2, and not any object that equals obj2;

        MyType obj = new MyType { prop1 = "foo", prop2 = "bar" };
        MyType obj2 = new MyType { prop1 = "foo", prop2 = "bar" };

        List<MyType> lstObj = new List<MyType> { obj2 };

        CollectionAssert.Contains(lstObj, obj2);

In other words, CollectionAssert.Contains compares instances and List(T).Contains "determines equality by using the default equality comparer, as defined by the object's implementation of the IEquatable.Equals method for T (the type of values in the list)."

Reference : http://msdn.microsoft.com/en-us/library/bhkz42b3.aspx

Share:
16,566

Related videos on Youtube

Daniel
Author by

Daniel

Updated on June 04, 2022

Comments

  • Daniel
    Daniel almost 2 years

    I have been looking at implementing unit tests for a controller controller, specifically around testing collections. On the MSDN example the use of CollectionAssert.Contains() confirms whether an object appears in a list.

    I have a List<myObject> where myObject implements IEquatable (i.e. implementing a Equals(), so that the List<myObject>.Contains() is able to correctly discern the existence (or non-existence of an object of type myObject in the list).

    The CollectionAssert.Contains() (for an MS-VS test, not nunit) function however, does not appear to call Equals(). So I'm wondering if it's for use on simple arrays? If not, how is it able to compare custom objects?

    I've simply changed my assert in this case to Assert.IsTrue(myList.Contains(myObjectInstance)).

  • Gishu
    Gishu over 12 years
    "Thanks, but thats my point. Equals that I've implemented is called by list<>.contains, but not by collectableassert.contains... So, as in the title of the thread, I have assert.istrue with list<>.Contains passing as expected where collectableassert.Contains fails. This is not the nunit test, but using vs tests so am not sure what the code does. Nunit behaviour maybe different. apologies, written on my phone! Smart phones aren't quite there yet tech wise." -- For Daniel [who seems to not have the rep to comment yet]
  • Palle Due
    Palle Due over 2 years
    For users reading this dated answer I can say: I ran into the exact same issue, I had implemented IEquatable and CollectionAssert.Contains didn't work. I implemented Equals(object obj) to call the strongly typed Equals and CollectionAssert.Contains work now. Super good information.