How to unit test if my object is really serializable?

后端 未结 7 1181
情书的邮戳
情书的邮戳 2020-12-03 00:45

I am using C# 2.0 with Nunit Test. I have some object that needs to be serialized. These objects are quite complex (inheritance at different levels and contains a lot of obj

相关标签:
7条回答
  • 2020-12-03 01:18

    Here is a solution that recursively uses IsSerializable to check that the object and all its properties are Serializable.

        private static void AssertThatTypeAndPropertiesAreSerializable(Type type)
        {
            // base case
            if (type.IsValueType || type == typeof(string)) return;
    
            Assert.IsTrue(type.IsSerializable, type + " must be marked [Serializable]");
    
            foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                if (propertyInfo.PropertyType.IsGenericType)
                {
                    foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments())
                    {
                        if (genericArgument == type) continue; // base case for circularly referenced properties
                        AssertThatTypeAndPropertiesAreSerializable(genericArgument);
                    }
                }
                else if (propertyInfo.GetType() != type) // base case for circularly referenced properties
                    AssertThatTypeAndPropertiesAreSerializable(propertyInfo.PropertyType);
            }
        }
    
    0 讨论(0)
  • 2020-12-03 01:21

    In addition to the test above - which makes sure the serializer will accept your object, you need to do a round-trip test. Deserialize the results back to a new object and make sure the two instances are equivalent.

    0 讨论(0)
  • 2020-12-03 01:26

    Probably a bit late in the day, but if you are using the FluentAssertions library, then it has custom assertions for XML serialization, binary serialization, and data contract serialization.

    theObject.Should().BeXmlSerializable();
    theObject.Should().BeBinarySerializable();
    theObject.Should().BeDataContractSerializable();
    
    theObject.Should().BeBinarySerializable<MyClass>(
        options => options.Excluding(s => s.SomeNonSerializableProperty));
    
    0 讨论(0)
  • 2020-12-03 01:29

    Unfortunately, you can't really test for this. Imagine this case:

    [Serializable]
    class Foo {
        public Bar MyBar { get; set; }
    }
    
    [Serializable]
    class Bar {
        int x;
    }
    
    class DerivedBar : Bar {
    }
    
    public void TestSerializeFoo() {
        Serialize(new Foo()); // OK
        Serialize(new Foo() { MyBar = new Bar() }; // OK
        Serialize(new Foo() { MyBar = new DerivedBar() }; // Boom
    }
    
    0 讨论(0)
  • 2020-12-03 01:36

    serialize the object (to memory or disk), deserialize it, use reflection to compare the two, then run all of the unit tests for that object again (except serialization of course)

    this assumes that your unit tests can accept an object as a target instead of making their own

    0 讨论(0)
  • 2020-12-03 01:40

    Here is a generic way:

    public static Stream Serialize(object source)
    {
        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        formatter.Serialize(stream, source);
        return stream;
    }
    
    public static T Deserialize<T>(Stream stream)
    {
        IFormatter formatter = new BinaryFormatter();
        stream.Position = 0;
        return (T)formatter.Deserialize(stream);
    }
    
    public static T Clone<T>(object source)
    {
        return Deserialize<T>(Serialize(source));
    }
    
    0 讨论(0)
提交回复
热议问题