4
\$\begingroup\$

I'm adding a function to my test library to assist in testing if two IDictionary objects contain the same keys/values.

I need the method to be generic and support a dictionary that has collections as values. So I thought I'd try to do it without using class types.

It appears to be working, but I would like to clarify that I didn't make any mistakes that would impact my tests later.

    /// <summary>
    /// Checks if two dictionaries contain the same values. Supports recursive
    /// dictionaries and collections as values.
    /// </summary>
    /// <param name="pExpect">Expected value</param>
    /// <param name="pActual">Actual value</param>
    // ReSharper disable CanBeReplacedWithTryCastAndCheckForNull
    public static void dictionary(IDictionary pExpect, IDictionary pActual)
    {
        Assert.IsNotNull(pExpect);
        Assert.IsNotNull(pActual);

        if (pExpect.Keys.Count != pActual.Keys.Count)
        {
            Assert.Fail("Expected {0} keys, but contains {1} keys.", pExpect.Keys.Count, pActual.Keys.Count);
        }

        object[] expectKeys = new object[pExpect.Keys.Count];
        object[] actualKeys = new object[pExpect.Keys.Count];

        pExpect.Keys.CopyTo(expectKeys, 0);
        pActual.Keys.CopyTo(actualKeys, 0);

        // check if the two key sets are the same
        CollectionAssert.AreEquivalent(expectKeys, actualKeys);

        for (int i = 0, c = expectKeys.Length; i < c; i++)
        {
            object expect = pExpect[expectKeys[i]];
            object actual = pActual[actualKeys[i]];

            // both can be null
            if (expect == null && actual == null)
            {
                continue;
            }

            // both must be assigned a value
            Assert.IsNotNull(expect);
            Assert.IsNotNull(actual);

            // must be same types
            Assert.AreEqual(expect.GetType(), actual.GetType());

            if (expect is IDictionary)
            {
                // support recursive dictionary checks
                dictionary((IDictionary)expect, (IDictionary)actual);
            }
            else if (expect is ICollection)
            {
                CollectionAssert.AreEquivalent((ICollection)expect, (ICollection)actual);
            }
            else
            {
                Assert.AreEqual(expect, actual);
            }
        }
    }

I am wondering if my last check Assert.AreEqual(expect, actual) will cover most remaining test cases.

EDIT: Fixed testing dictionaries that have keys in different orders.

\$\endgroup\$
4
\$\begingroup\$

Your code doesn't work, because items in a dictionary aren't ordered in any way.

Example code that fails your test:

dictionary(
    new Dictionary<int, int> { { 0, 0 }, { 1, 1 } },
    new Dictionary<int, int> { { 1, 1 }, { 0, 0 } });

Some more notes about your code:

public static void dictionary(IDictionary pExpect, IDictionary pActual)

dictionary is a bad name for this method, because it doesn't really explain what it's supposed to do. Something like DictionaryEqualityTest would be better.

Also, I would avoid using the non-generic IDictionary if possible, IDictionary<TKey, TValue> would be better (though it would complicate the recursion).

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ thanks for the fail. I'll see if I can fix it. I know the name is weak, but it's in a class called "Same" which does nothing but same checks. \$\endgroup\$ – Reactgular Nov 12 '13 at 22:17
  • \$\begingroup\$ I fixed the problem and updated the question. thanks for the help. \$\endgroup\$ – Reactgular Nov 12 '13 at 23:25
2
\$\begingroup\$

You could get an endless recursion with the following code:

var dict1 = new Hashtable(); 
var dict2 = new Hashtable();
dict1.Add(1,dict1);
dict2.Add(1,dict2);
dictionary(dict1,dict2);
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.