views:

301

answers:

4

I ran into a bug in some code that extracts metadata from some text and puts it into a dictionary.

My test was failing when I compared two dictionary objects because the keys were in different order. I don't really care what order the keys are in.

I'd like to have an assert method available like :

Assert.AreEquivalent(propsExpected,propsActual)

That would evaluate like:

Assert.AreEqual(propsExpected.Count, propsActual.Count);
foreach (var key in propsExpected.Keys)
{
    Assert.IsNotNull(props[key]);
    Assert.AreEqual(propsExpected[key], props[key]);
}

What's the best way to do this?

+1  A: 

If you are able to use LINQ,


void Main()
{
    Dictionary d1 = new Dictionary<int, string>();
    Dictionary d2 = new Dictionary<int, string>();  

    d1.Add(1, "1");
    d1.Add(2, "2");  
    d1.Add(3, "3");  

    d2.Add(2, "2");  
    d2.Add(1, "1");  
    d2.Add(3, "3");  

    Console.WriteLine(d1.Keys.Except(d2.Keys).ToArray().Length);  
}

This prints 0 to the console. Except tries to find the difference between two lists in the above example.

You can compare this with 0 to find if there is any difference.

EDIT: You could add the check for comparing the length of 2 dictionaries before doing this.
i.e. You can use Except, only if the length differs.

shahkalpesh
A: 

From these posts it looks like MbUnit already supports this with AreElementsEqualIgnoringOrder.

http://japikse.blogspot.com/2008/12/my-favorite-mbunit-assertions.html

http://blog.bits-in-motion.com/2008/10/announcing-gallio-and-mbunit-v304.html

Maggie
+5  A: 

The trick here is to use a new feature of .Net 3.5 called extension methods

For example to get the Assert class to support the AreEquivalent method using the code you supplied above, you would do something like this:

public static class MyAssertExtensions
{
    public static void AreEquivalent(this Assert ast, 
     Dictionary<string, int> propsExpected, 
     Dictionary<string, int> propsActual)
    {
     Assert.AreEqual(propsExpected.Count, propsActual.Count);
     foreach (var key in propsExpected.Keys)
     {
      Assert.IsNotNull(props[key]);
      Assert.AreEqual(propsExpected[key], props[key]);
     }
    }
}

This way you can actually call the assertion like this:

Assert.AreEquivalent(propsExpected,propsActual);
Michael La Voie
The problem here is that if the elements in the two dictionaries don't have the same order, the assertion will fail even if the elements are equals
Marwan Aouida
@Marwan: no, it only asserts that the collections are the same size and that, for every key in collection 1, the same key also exists in collection 2 with the same value. Order is never an issue.
GalacticCowboy
@GalacticCowboy yes I understood now.
Marwan Aouida
I'll try this, thanks!
Kevin Davis
This won't work, as you can't extend a static type.. :(
Sprintstar
A: 

With NUnit, you can compare two collections using the Is.EquivalentTo() constraint. This constraint will evaluate the collection and check whether the collection has the same elements, but it doesn't care about the order.

Documentation for CollectionEquivalentConstraint If you don't use NUnit, then maybe something similar exists in the testing framework you're using?

Mark Simpson