What is the right way to compare as3 objects using hamcrest

1.5k views Asked by At

I'm trying to compare two objects to see if they are the same using hamcrest for flex-unit, but when the object has sub objects, it just throws an error:

Error: Expected: (An array containing <[object Object]>
but: an array containing <[object Object]> was <[object Object]>

I want it to do an assertThat(..., hasProperties(...)); on the sub object.

Is there a way to get that or should i create a custom matcher?

EDIT

An example of the object structure i want to test:

var expected:Object = {
    number:1.3,
    array:[{
        prop1:"val1", prop2:"val2"
    }]
    anObject:{
        propA:1, propB:2
    },
}

var objectUnderTest:Object = {
    number:1.3,
    array:[{
        prop1:"val1", prop2:"val2"
    }]
    anObject:{
        propA:1, propB:2
    },
}

assertThat("should be the same", objectUnderTest, hasProperties(expected));

since the expected and objectUnderTest have the same structure, the test should pass, but is returning the error:

Error: Expected: (An array containing <[object Object]>
but: an array containing <[object Object]> was <[object Object]>

Also, if there is a way to compare two JSON strings will be fine too.

EDIT2

This is my final version after djib help:

package com
{
    public function assertEqualsObjects(message:String, object1:Object, object2:Object):Boolean
    {
        // we have to run it both ways (1-2, 2-1)
        return (compare(object1, object2, message + ": object") && compare(object2, object1, message + ": extra"));
    }
}

import org.flexunit.asserts.fail;

function compare(object1:Object, object2:Object, parent:String):Boolean
{
    var count:int = 0;

    for (var s:String in object1)
    {
        count ++;
        if (!object2.hasOwnProperty(s))
        {
            fail(parent + "." + s + " expected: " + object1[s] + " but was: undefined");
            return false;
        }
        if (!compare(object1[s], object2[s], parent + "." + s))
        {
            fail(parent + "." + s + " expected: " + object1[s] + " but was: " + object2[s]);
            return false;
        }
    }

    if (count == 0 && object1 != object2) // if object has no properties, compare their actual values
    {
        fail(parent + " expected: " + object1 + " but was: " + object2);
        return false;
    }

    return true;
}
1

There are 1 answers

1
djib On

I've put this code together. Recursion is the key ^^

        // our two objects to compare ...
        var obj1 = {
            number:1.3,
            array:[{prop1:"val1", prop2:"val2"}],
            anObject:{propA:1, propB:2}
        };

        var obj2 = {
            number:1.3,
            array:[{prop1:"val1", prop2:"val2"}],
            anObject:{propA:1, propB:2}
        };

        trace(isSame(obj1, obj2)); // -> true


    function isSame(object1:Object, object2:Object):Boolean
    {
        // we have to run it both ways (1-2, 2-1)
        return (compare(object1, object2) && compare(object2, object1));
    }

    function compare(object1:Object, object2:Object):Boolean
    {
        var count:int = 0;

        for (var s:String in object1)
        {
            count ++;
            if (object2[s] == undefined)
                return false;
            if (!compare(object1[s], object2[s]))
                return false;
        }

        if (count == 0 && object1 != object2) // if object has no properties, compare their actual values
        return false;

        return true;
    }