单元测试序列化有什么意义吗?

Chr*_*s S 14 c# serialization unit-testing xml-serialization

我有一个类,它序列化一组对象(使用XML序列化),我想要进行单元测试.

我的问题是感觉我将测试XML序列化的.NET实现,而不是任何有用的.我还有一个轻微的鸡蛋和鸡蛋场景,为了测试Reader,我需要一个由Writer生成的文件来这样做.

我认为问题(有3个但它们都有关系)我最终都在寻找反馈意见:

  1. 是否可以在不使用Reader的情况下测试Writer?
  2. 测试阅读器的最佳策略是什么(XML文件?记录/回放模拟)?是否所有您真正要做的是测试已反序列化的对象的属性值?
  3. 测试作者的最佳策略是什么!

关于Xml序列化的背景信息

我没有使用模式,因此所有XML元素和属性都与对象的属性相匹配.由于没有架构,因此XmlSerializer会忽略与每个对象的属性中找不到的架构/属性不匹配的标签/属性(因此属性的值为null或默认值).这是一个例子

<MyObject Height="300">
    <Name>Bob</Name>
    <Age>20</Age>
<MyObject>
Run Code Online (Sandbox Code Playgroud)

会映射到

public class MyObject
{
  public string Name { get;set; }
  public int Age { get;set; }

  [XmlAttribute]
  public int Height { get;set; }
}
Run Code Online (Sandbox Code Playgroud)

反之亦然.如果对象更改为以下,则XML仍将成功反序列化,但FirstName将为空.

public class MyObject
{
  public string FirstName { get;set; }
  public int Age { get;set; }

  [XmlAttribute]
  public int Height { get;set; }
}
Run Code Online (Sandbox Code Playgroud)

无效的XML文件将正确反序列化,因此除非您对MyObject的值运行断言,否则单元测试将通过.

Jon*_*eet 26

你需要能够向后兼容吗?如果是这样,可能值得建立旧版本生成的文件的单元测试,这些文件仍然可以通过新版本进行反序列化.

除此之外,如果你介绍任何"有趣"的东西,可能值得单元测试,只是检查你可以序列化和反序列化只是为了确保你没有做一些与readonly属性等时髦的东西.

  • 我说这仍然足以让它值得测试. (3认同)

Mar*_*ell 19

我认为,如果在版本之间读取数据至关重要,那么对单元测试序列化至关重要.并且您必须使用"已知良好"数据进行测试(即仅仅在当前版本中编写数据然后再次读取数据是不够的).

你提到你没有架构......为什么不生成架构呢?要么用手(不是很难),要么用xsd.exe.然后你可以使用一些东西作为模板,你可以使用它来验证这一点XmlReader.我目前正在使用xml序列化做很多工作,更新架构要比担心我是否正确获取数据要容易得多.

甚至XmlSerializer可以变得复杂; 特别是如果您涉及subslasses([XmlInclude]),自定义序列化(IXmlSerializable)或非默认XmlSerializer构造(在运行时将其他元数据传递给ctor).另一种可能性是创造性地使用[XmlIngore],[XmlAnyAttribute][XmlAnyElement]; 例如,您可能在版本X中支持往返(仅)的意外数据,但将其存储在版本Y中的已知属性中.


通常序列化:

原因很简单:你可以打破数据!你这么做有多糟糕取决于序列化器; 例如,BinaryFormatter(我知道问题是XmlSerializer),只需改变:

public string Name {get;set;}
Run Code Online (Sandbox Code Playgroud)

private string name;
public string Name {
    get {return name;}
    set {name = value; OnPropertyChanged("Name"); }
}
Run Code Online (Sandbox Code Playgroud)

可能足以打破序列化,因为字段名称已更改(并且BinaryFormatter喜欢字段).

在其他情况下,您可能会意外地重命名数据(即使在基于合同的序列化程序中,例如XmlSerializer/ DataContractSerializer).在这种情况下,您通常可以覆盖电线标识符(例如[XmlAttribute("name")]等),但重要的是检查一下!

最终,它归结为:您是否可以阅读旧数据?通常是; 所以不要只发货... 证明你可以.


Red*_*ter 7

对我来说,这绝对是在Do not Bother类别中.我没有对我的工具进行单元测试.但是,如果您编写了自己的序列化类,那么请务必对其进行单元测试.


adr*_*nks 5

如果您想确保对象的序列化不会破坏,那么一定要进行单元测试.如果您阅读XMLSerializer类的MSDN文档:

XmlSerializer无法序列化或反序列化以下内容:List <T>

的ArrayList
数组

枚举声明为unsigned longs也存在一个特殊问题.此外,标记为" [Obsolete]不"的任何对象都将从.Net 3.5开始进行序列化.

如果您有一组被序列化的对象,那么测试序列化可能看起来很奇怪,但只需要有人编辑被序列化的对象,以包含序列化中断的不受支持的条件之一.

实际上,您不是单元测试XML序列化,而是测试您的对象是否可以序列化.这同样适用于反序列化.