Comment faire un test unitaire si mon objet est vraiment sérialisable?

j'utilise C# 2.0 avec le test Nunit. J'ai un objet qui doit être sérialisé. Ces objets sont assez complexes (héritage à différents niveaux et contient beaucoup d'objets, des événements et des délégués).

Comment puis-je créer un test unitaire pour être sûr que mon objet est sérialisable en toute sécurité?

31
demandé sur Joel Coehoorn 2008-10-25 19:47:00

7 réponses

j'ai ceci dans un test d'Unité ici à 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);
}

pourrait vous aider... peut-être que d'autres méthodes peuvent être mieux mais celle-ci fonctionne bien.

14
répondu Patrick Desjardins 2010-11-01 18:24:57

Voici une voie Générique:

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));
}
42
répondu GeverGever 2011-10-03 13:52:14

en plus du test ci - dessus-qui assure que le serializer acceptera votre objet, vous devez faire un test aller-retour. Désérialisez les résultats vers un nouvel objet et assurez-vous que les deux instances sont équivalentes.

13
répondu Scott Weinstein 2008-10-25 18:15:58

sérialiser l'objet (en mémoire ou sur disque), le desérialiser, utiliser la réflexion pour comparer les deux, puis exécuter à nouveau tous les tests unitaires pour cet objet (sauf la sérialisation bien sûr)

cela suppose que vos tests unitaires peuvent accepter un objet comme cible au lieu de faire leur propre

3
répondu Steven A. Lowe 2008-10-25 16:19:31

Voici une solution qui utilise de façon récursive Isserialisable pour vérifier que l'objet et toutes ses propriétés sont sérialisables.

    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);
        }
    }
2
répondu Zaid Masud 2011-01-05 16:42:02

malheureusement, vous ne pouvez pas vraiment tester pour cela. Imaginez ce cas:

[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
}
1
répondu erikkallen 2012-12-19 08:58:40

probablement un peu en retard dans la journée, mais si vous utilisez la bibliothèque FluentAssertions , alors il a des assertions personnalisées pour la sérialisation XML, la sérialisation binaire, et la sérialisation de contrat de données.

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

theObject.Should().BeBinarySerializable<MyClass>(
    options => options.Excluding(s => s.SomeNonSerializableProperty));
0
répondu David Keaveny 2017-10-18 09:09:07