簡體   English   中英

如何對我的對象是否真正可序列化進行單元測試?

[英]How to unit test if my object is really serializable?

我在Nunit Test中使用C#2.0。 我有一些需要序列化的對象。 這些對象非常復雜(不同級別的繼承,並且包含許多對象,事件和委托)。

如何創建單元測試以確保對象可以安全地序列化?

這是一種通用方法:

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

我在工作中進行一些單元測試:

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

可能會對您有所幫助...也許其他方法可能更好,但是這種方法效果很好。

除了上述測試(可確保序列化程序將接受您的對象)外,您還需要進行往返測試。 將結果反序列化回新對象,並確保兩個實例等效。

序列化對象(到內存或磁盤),反序列化,使用反射將兩者進行比較,然后再次運行該對象的所有單元測試 (當然,序列化除外)

這假設您的單元測試可以接受一個對象作為目標,而不是自己創建一個對象

這是一個遞歸使用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);
        }
    }

不幸的是,您無法對此進行真正的測試。 想象一下這種情況:

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

可能要花點時間 ,但是如果您使用FluentAssertions庫,那么它具有針對XML序列化,二進制序列化和數據協定序列化的自定義斷言。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM