C# 如何单元测试我的对象是否真的可序列化?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/236599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:18:12  来源:igfitidea点击:

How to unit test if my object is really serializable?

c#.netunit-testingserialization.net-2.0

提问by Pokus

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 objects, events and delegates).

我在 Nunit 测试中使用 C# 2.0。我有一些需要序列化的对象。这些对象相当复杂(不同层次的继承,包含大量的对象、事件和委托)。

How can I create a Unit Test to be sure that my object is safely serializable?

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

采纳答案by Patrick Desjardins

I have this in some unit test here at job:

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

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

Might help you... maybe other method can be better but this one works well.

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

回答by Scott Weinstein

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.

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

回答by Steven A. Lowe

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

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

回答by GeverGever

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

回答by Zaid Masud

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

这是一个递归使用 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);
        }
    }

回答by erikkallen

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
}

回答by David Keaveny

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

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

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

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