如果我的对象真的可序列化,如何进行单元测试?

时间:2008-10-25 15:47:01

标签: c# .net unit-testing serialization .net-2.0

我正在使用C#2.0和Nunit Test。我有一些需要序列化的对象。这些对象非常复杂(在不同级别继承并包含许多对象,事件和委托)。

如何创建单元测试以确保我的对象可以安全地序列化?

7 个答案:

答案 0 :(得分:45)

这是一种通用方式:

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));
}

答案 1 :(得分:15)

我在工作中的一些单元测试中有这个:

MyComplexObject dto = new MyComplexObject();
MemoryStream mem = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
try
{
    b.Serialize(mem, dto);
}
catch (Exception ex)
{
    Assert.Fail(ex.Message);
}

可能会帮助你...也许其他方法可能会更好但是这个方法效果很好。

答案 2 :(得分:14)

除了上面的测试 - 确保序列化程序将接受您的对象,您需要进行往返测试。将结果反序列化回新对象,并确保两个实例是等效的。

答案 3 :(得分:3)

序列化对象(到内存或磁盘),反序列化它,使用反射比较两者,然后再次运行该对象的所有单元测试(当然序列化除外)

这假设你的单元测试可以接受一个对象作为目标而不是自己的

答案 4 :(得分:2)

这是一个递归使用IsSerializable来检查对象及其所有属性是否可序列化的解决方案。

    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);
        }
    }

答案 5 :(得分:1)

不幸的是,你无法真正测试这一点。想象一下这个案例:

[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
}

答案 6 :(得分:1)

当天可能有点晚了,但是如果您使用的是FluentAssertions库,那么它就会有XML序列化,二进制序列化和数据协定序列化的自定义断言。

theObject.Should().BeXmlSerializable();
theObject.Should().BeBinarySerializable();
theObject.Should().BeDataContractSerializable();

theObject.Should().BeBinarySerializable<MyClass>(
    options => options.Excluding(s => s.SomeNonSerializableProperty));