views:

46

answers:

3

From MBUnit I am trying to check if the values of two objects are the same using

Assert.AreSame(RawDataRow, result);

However I am getting the following fail:

Expected Value & Actual Value : {RawDataRow: CentreID = "CentreID1",
CentreLearnerRef = "CentreLearnerRef1",
ContactID = 1, DOB = 2010-05-05T00:00:00.0000000,
Email = "Email1", ErrorCodes = "ErrorCodes1",
ErrorDescription = "ErrorDescription1", FirstName = "FirstName1"}

Remark : Both values look the same when formatted but they are distinct instances.

I don't want to have to go through each property. Can I do this from MbUnit?

A: 

Are you specifically looking for referential equality? AreSame is testing that both references point to the same object. From the doco:

Assert.AreSame - Verifies that an actual value is referentially identical to some expected value.

If you are simply looking to compare that two instances of an object are logically equal, then AreEqual is what you need.

Assert.AreEqual - Verifies that an actual value equals some expected value.

serg10
That is what I thought, but I get the same result for this too
Coppermill
Just for reference:Using Assert.AreEqual or Assert.AreSame returns "Remark : Both values look the same when formatted but they are distinct instances."
Coppermill
A: 

I've ended up building my own using Reflections

private bool PropertiesEqual<T>(T object1, T object2)
        {
            PropertyDescriptorCollection object2Properties = TypeDescriptor.GetProperties(object1);
            foreach (PropertyDescriptor object1Property in TypeDescriptor.GetProperties(object2))
            {
                PropertyDescriptor object2Property = object2Properties.Find(object1Property.Name, true);

                if (object2Property != null)
                {
                    object object1Value = object1Property.GetValue(object1);
                    object object2Value = object2Property.GetValue(object2);

                    if ((object1Value == null && object2Value != null) || (object1Value != null && object2Value == null))
                    {
                        return false;
                    }

                    if (object1Value != null && object2Value != null)
                    {
                        if (!object1Value.Equals(object2Value))
                        {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
Coppermill
It will work fine. But MbUnit has a built-in structural equality comparer already (see my answer).
Yann Trevin
+1  A: 

Basically, Assert.AreEqual uses Object.Equals() to verify the equality between the actual and the expected instance, while Assert.AreSame uses Object.ReferenceEquals.

If your class does not implement any built-in equality mechanism; for example by overriding Object.Equals, you will end up with the issue you describe because MbUnit does not know how to compare two instances of the type under test.

There are several solutions. One of them is Coppermill's solution: you may want to implement a structural equality comparer based on reflection. But MbUnit has already a built-in feature like that. It's called StructuralEqualityComparer<T> and it's very easy to use. So why reinventing the wheel?

Assert.AreSame(RawDataRow, result, new StructuralEqualityComparer<MyDataRow>
{
   { x => x.CentreID },
   { x => x.CentreLearnerRef, (a, b) => a.Equals(b, StringComparison.OrdinalIgnoreCase) },
   { x => x.ContactID },
   // You can customize completely the comparison process...
});

Anyway, I suggest you read that article: http://interfacingreality.blogspot.com/2009/09/equality-assertions-in-mbunit-v3.html

You may also want to read that article in the Gallio wiki.

Yann Trevin
I do love that feature. :)
Jeff Brown