Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perform Assert.AreMatch() to deep compare properties in two objects

I am writing tests against our Caching mechanism and I want to be sure that what goes into the cache is the same as what comes out, ie that all properties match. Here is a fictional example of how I would like it to work

    [Test]
    public void add_client_model_member_to_cache_then_retreve()
    {
        //arrange
        MemcachedClient client = new MemcachedClient();
        Member member = GetMember();
        client.Store(StoreMode.Set, "membertest", member);

        // act
        var result = client.Get<Member>("membertest");

        // assert
        Assert.AreMatch(result, member);
    }

It is not feasible to perform Assert.AreEqual on each property as there will be many of these tests with many properties in each.

Wow, thanks Jon. I think you answered that in under one minute. Here are my resulting solution for any interested parties. I implemented as Jon suggested (I think) however I got into a little trouble with array properties and as such my solution only handles arrays of ints (all I currently require).

It also got to be a fairly slippery slope if I try to check deeper than one level. I am sure this can be achieved however for my purposes it is not required.

private bool AreMatch(object initial, object result)
    {
        if (initial.Equals(result)) 
            return true;

        foreach (var property in initial.GetType().GetProperties())
        {
            var initialPropValue = property.GetValue(initial,null);
            var resultPropValue = result.GetType().GetProperty(property.Name).GetValue(result,null);

            if (property.PropertyType.IsArray)
            {
                if ((initialPropValue != null && resultPropValue != null) && !Enumerable.SequenceEqual((int[])initialPropValue, (int[])resultPropValue))
                        return false;                   
            }
            else if (!object.Equals(initialPropValue, resultPropValue))
            {
                return false;
            }
            else if (initialPropValue != null && property.PropertyType.IsClass)
            {
                // Don't go deeper than one level, this got me into trouble
                //if (!AreMatch(initialPropValue, resultPropValue))
                //  return false;
            }
        }
        return true;
    }

The method above can be used in the following situations

    [Test]
    public void cached_result_is_same_as_original()
    {
        //arrange
        Member member = GetMember();
        client.Store(StoreMode.Set, "membertest", member);

        // act
        var result = client.Get<Member>("membertest");

        // assert
        Assert.IsTrue(AreMatch(member, result));
    }

    [Test]
    public void cached_result_is_same_as_original()
    {
        //arrange
        Member member = GetMember();
        client.Store(StoreMode.Set, "membertest", member);

        // act
        var result = client.Get<Member>("membertest");
        result.FirstName = "Result is different"; 

        // assert
        Assert.IsFalse(AreMatch(member, result));
    }
like image 255
CodeKiwi Avatar asked Aug 16 '10 22:08

CodeKiwi


People also ask

How to compare two objects properties in JavaScript?

Objects are not like arrays or strings. So simply comparing by using "===" or "==" is not possible. Here to compare we have to first stringify the object and then using equality operators it is possible to compare the objects.

How to check if two objects are same in JavaScript?

The referential equality (using === , == or Object.is() ) determines whether the operands are the same object instance. The manual equality check requires a manual comparison of properties' values.


1 Answers

Well, you could certainly write something to recurse through all the properties, and call object.Equals on the result of fetching the property value from the expected and actual ones. Use Type.GetProperties() to get the properties themselves, and PropertyInfo.GetValue to get the value.

It'll be somewhat crude, but you could always tweak it if necessary.

like image 98
Jon Skeet Avatar answered Oct 26 '22 22:10

Jon Skeet