NUnit Equality Comparer incorrectly defines equality for Dictionary objects

Bug #608875 reported by Chris Hefley
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
NUnit Framework
Medium
Charlie Poole
NUnit V2
Fix Released
Medium
Charlie Poole

Bug Description

Using Version 2.5.4

This assertion passes

            Assert.That(new Dictionary<int, int> { { 0, 0 }, { 1, 1 }, { 2, 2 } } == new Dictionary<int, int> { { 0, 0 }, { 2, 2 }, { 1, 1 } });

While this one does not

            Assert.AreEqual(new Dictionary<int, int> { { 0, 0 }, { 1, 1 }, { 2, 2 } }, new Dictionary<int, int> { { 0, 0 }, { 2, 2 }, { 1, 1 } });

Order is not preserved in a dictionary, and the standard object.equals for dictionary objects will ignore the order in which items were added to the Dictionary.

The offending code in NUnit is in the NUnitEqualityComparer class, line 129

           if (x is ICollection && y is ICollection)
                return CollectionsEqual((ICollection)x, (ICollection)y);

Since Dictionary implements ICollection, two dictionary objects being compared will be sent through the CollectionsEqual method, which enforces that the elements in the ICollection must match by index.

            IEnumerator expectedEnum = x.GetEnumerator();
            IEnumerator actualEnum = y.GetEnumerator();

            int count;
            for (count = 0; expectedEnum.MoveNext() && actualEnum.MoveNext(); count++)
            {
                if (!ObjectsEqual(expectedEnum.Current, actualEnum.Current))
                    break;
            }

To fix it, you'll need to check whether the objects being compared implement IDictionary before checking to see if they implement ICollection, and handle them accordingly. I believe you can probably just use object.equals without providing a specialized equality comparison for Dictionaries.

Related branches

Changed in nunitv2:
status: New → Triaged
importance: Undecided → Medium
Changed in nunit-3.0:
status: New → Triaged
importance: Undecided → Medium
Changed in nunitv2:
assignee: nobody → Charlie Poole (charlie.poole)
milestone: none → 2.5.6
Revision history for this message
Charlie Poole (charlie.poole) wrote :

Shortened title to make it fit better in listings - removed info is in the description.

summary: NUnit Equality Comparer incorrectly defines equality for Dictionary
- objects based on them being in the same sequence, as an unintended
- consequence of treating all ICollection objects the same
+ objects
Revision history for this message
Charlie Poole (charlie.poole) wrote :

This now works for any IDictionary, including comparisons between different types of dictionaries.

Changed in nunitv2:
status: Triaged → Fix Committed
tags: added: v2port
Changed in nunit-3.0:
assignee: nobody → Charlie Poole (charlie.poole)
milestone: none → 2.9.5
status: Triaged → Won't Fix
status: Won't Fix → Fix Committed
Changed in nunitv2:
status: Fix Committed → Fix Released
Changed in nunit-3.0:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers