c# - serialize - ¿Cómo probar mi unidad si mi objeto es realmente serializable?
serializar una clase c# (7)
Estoy usando C # 2.0 con Nunit Test. Tengo un objeto que necesita ser serializado. Estos objetos son bastante complejos (herencia en diferentes niveles y contiene muchos objetos, eventos y delegados).
¿Cómo puedo crear una prueba unitaria para asegurarme de que mi objeto se puede serializar con seguridad?
Además de la prueba anterior, que asegura que el serializador aceptará su objeto, debe realizar una prueba de ida y vuelta. Deserialice los resultados a un nuevo objeto y asegúrese de que las dos instancias sean equivalentes.
Aquí hay una manera genérica:
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));
}
Aquí hay una solución que recursivamente usa IsSerializable para verificar que el objeto y todas sus propiedades sean serializables.
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);
}
}
Lamentablemente, no puedes realmente probar esto. Imagina este caso:
[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
}
Probablemente un poco tarde en el día, pero si está utilizando la biblioteca FluentAssertions , entonces tiene aserciones personalizadas para serialización XML, serialización binaria y serialización de contrato de datos.
theObject.Should().BeXmlSerializable();
theObject.Should().BeBinarySerializable();
theObject.Should().BeDataContractSerializable();
theObject.Should().BeBinarySerializable<MyClass>(
options => options.Excluding(s => s.SomeNonSerializableProperty));
Tengo esto en una prueba unitaria aquí en el trabajo:
MyComplexObject dto = new MyComplexObject();
MemoryStream mem = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
try
{
b.Serialize(mem, dto);
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
Podría ayudarlo ... tal vez otro método puede ser mejor, pero este funciona bien.
serializar el objeto (a la memoria o al disco), deserializarlo, usar la reflexión para comparar los dos, luego ejecutar nuevamente todas las pruebas unitarias para ese objeto (excepto la serialización del curso)
esto supone que las pruebas de su unidad pueden aceptar un objeto como objetivo en lugar de hacer su propio