views:

95

answers:

2

Has anyone seen a library that tests WCF DataContracts? The motivation behind asking this is that I just found a bug in my app that resulted from my not annotating a property with the DataMember attribute - as a result, that property wasn't being serialized.

What I have in mind is an API that, given a particular type of DataContract, will automatically populate its members with random data, including any child DataContracts, then serialize it via one of the WCF Serializers/Formatters and then check that all of the data has been carried across.

Anyone?

+1  A: 

This might not be what you're looking for but with WCFStorm if you try to add a service and that service had a property not marked with the DataMember attribute, that property will not show up in the Tree display. That would give you a clue that something is wrong with the property.

+1  A: 

It's simple enough to use DataContractSerializer to serialise your object to a MemoryStream, then deserialise it back into existence as a new instance.

Here's a class that demonstrates this round-trip serialisation:

public static class WcfTestHelper
{
    /// <summary>
    /// Uses a <see cref="DataContractSerializer"/> to serialise the object into
    /// memory, then deserialise it again and return the result.  This is useful
    /// in tests to validate that your object is serialisable, and that it
    /// serialises correctly.
    /// </summary>
    public static T DataContractSerializationRoundTrip<T>(T obj)
    {
        return DataContractSerializationRoundTrip(obj, null);
    }

    /// <summary>
    /// Uses a <see cref="DataContractSerializer"/> to serialise the object into
    /// memory, then deserialise it again and return the result.  This is useful
    /// in tests to validate that your object is serialisable, and that it
    /// serialises correctly.
    /// </summary>
    public static T DataContractSerializationRoundTrip<T>(T obj, 
                    IEnumerable<Type> knownTypes)
    {
        var serializer = new DataContractSerializer(obj.GetType(), knownTypes);
        var memoryStream = new MemoryStream();
        serializer.WriteObject(memoryStream, obj);
        memoryStream.Position = 0;
        obj = (T)serializer.ReadObject(memoryStream);
        return obj;
    }
}

Two tasks that you are responsible for:

  • Populating the instance in the first place with sensible data. You might choose to use reflection to set properties or supply a constructor with its arguments, but I've found this approach just won't work for anything other than incredibly simple types.
  • Comparing the two instances after you have round-trip de/serialised it. If you have a reliable Equals/GetHashCode implementation, then that might already be done for you. Again you might try using a generic reflective comparer, but this mightn't be completely reliable.
Drew Noakes