如何单元测试我的对象是否真的可序列化
本文关键字:真的 序列化 是否 对象 单元测试 我的 | 更新日期: 2023-09-27 17:47:23
我正在使用带有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);
}
可能会帮助你...也许其他方法可以更好,但这种方法效果很好。
除了上面的测试 - 确保序列化程序接受你的对象,你还需要做一个往返测试。将结果反序列化回新对象,并确保两个实例等效。
可能有点
晚了,但是如果您使用的是 FluentAssertions 库,那么它具有用于 XML 序列化、二进制序列化和数据协定序列化的自定义断言。
theObject.Should().BeXmlSerializable();
theObject.Should().BeBinarySerializable();
theObject.Should().BeDataContractSerializable();
theObject.Should().BeBinarySerializable<MyClass>(
options => options.Excluding(s => s.SomeNonSerializableProperty));
序列化对象(到内存或磁盘),反序列化它,使用反射比较两者,然后再次运行该对象的所有单元测试(当然序列化除外)
这假定您的单元测试可以接受对象作为目标,而不是创建自己的对象
这是一个递归使用 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
}