XMLUnit使用总结

By | 5月 17, 2018

1. 可能导致out of memory issue

XMLUnit需要将整个XML加载到内存中,构建完成的DOM tree,然后进行比较。不支持SAX流式读取,所以当待比较的XML文件很大时,会导致内存溢出

2. Attribute order

官方文档说:

  • 1.X的版本,手动调用XMLUnit.setIgnoreAttributeOrder(boolean)。
  • 2.X的版本,Attribute order始终是忽略的。

项目中用的是1.X版本,发现XMLUnit.setIgnoreAttributeOrder(boolean)不起作用,attribute order也总是被忽略。

原因:

Java DOM读取XML attribute时,是按照字母顺序排序的,也就是有序。故,不管原XML attribute顺序如何,XMLUnit比较时,attribute始终有序。这也是为什么在XMLUnit 1.X版本,不管setIgnoreAttributeOrder是true或false,比较结果总是identical

String xml = "<root name='n1' id='1' a='a'/>";
// Use DOM load this xml string. And print each attribute name.
// ......
NamedNodeMap attributes = dom.getDocumentElement();
for (int i = 0; i< attributes.getLength(); i+) {
    System.out.print(attributes.item(i).getNodeName() + ", ");
}
// Output is ordered: a, id, name

3. Element order

当XML节点里,有多个同名的节点,此时比较都会失败。

<root>
    <name id="1">Jerry</name>
    <name id="2">Tom</name>
</root>
<root>
    <name id="2">Tom</name>
    <name id="1">Jerry</name>
</root>

对于左边的XML,当遇到第一个name节点(id是1,text是Jerry),XMLUnit会在右边root节点下找第一个叫做name的节点,则会找到id是2,text是Tom那个节点。一比较,发现id不匹配,text也不匹配,于是失败了。

失败原因是因为:XMLUnit默认使用ElementNameQualifier,也就是说仅仅根据节点名字来寻找比较节点。

Diff::overrideElementQualifier(new ElementQualifier()),调用此方法可以告诉XMLUnit如何寻找匹比较节点。

  • ElementNameQualifier:默认的,只看节点名字。
  • ElementNameAndAttributeQualifier:比较名字,同时比较节点Attribute。
  • ElementNameAndTextQualifier:比较名字,同时比较节点text。

对于上面的case,因为两个<name/>节点的attribute和text都不同,所以我们用ElementNameAndAttributeQualifier或ElementNameAndTextQualifier都可以使比较变成功。

Diff diff = XMLUnit.compareXML(expected, actual);
diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
assertTrue(diff.toString(), diff.identical());