我正在尝试对一些生成 xml 的方法进行单元测试。我有一个预期的 xml 字符串和结果字符串,在谷歌搜索和搜索堆栈溢出后,我找到了 XMLUnit。但是,它似乎无法处理一种特殊情况,即以不同顺序重复的元素包含不同顺序的元素。例如:
预期的 XML:
<graph>
<parent>
<foo>David</foo>
<bar>Rosalyn</bar>
</parent>
<parent>
<bar>Alexander</bar>
<foo>Linda</foo>
</parent>
</graph>
实际 XML:
<graph>
<parent>
<foo>Linda</foo>
<bar>Alexander</bar>
</parent>
<parent>
<bar>Rosalyn</bar>
<foo>David</foo>
</parent>
</graph>
您可以看到父节点重复,其内容可以按任意顺序排列。这两个 xml 片段应该是等效的,但是我见过的 stackoverflow 示例中没有任何东西可以解决这个问题。(在 Java 中比较 2 个 XML 文档的最佳方法)(如何在 XMLUnit 中比较两个相似的 XML 文件)
我已经求助于从 xml 字符串创建文档,单步执行每个预期的父节点,然后将其与每个实际的父节点进行比较,以查看其中一个是否等效。
在我看来,这似乎是为了一个相对常见的比较而重新发明轮子。XMLUnit 似乎做了很多,也许我错过了一些东西,但据我所知,在这种特殊情况下它还不够。
有没有更简单/更好的方法来做到这一点?
我的解决方案:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setCoalescing(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setIgnoringComments(true);
DocumentBuilder db = dbf.newDocumentBuilder();
// parse and normalize expected xml
Document expectedXMLDoc = db.parse(new ByteArrayInputStream(resultXML.getBytes()));
expectedXMLDoc.normalizeDocument();
// parse and normalize actual xml
Document actualXMLDoc = db.parse(new ByteArrayInputStream(actual.getXml().getBytes()));
actualXMLDoc.normalizeDocument();
// expected and actual parent nodes
NodeList expectedParentNodes = expectedXMLDoc.getLastChild().getChildNodes();
NodeList actualParentNodes = actualXMLDoc.getLastChild().getChildNodes();
// assert same amount of nodes in actual and expected
assertEquals("actual XML does not have expected amount of Parent nodes", expectedParentNodes.getLength(), actualParentNodes.getLength());
// loop through expected parent nodes
for(int i=0; i < expectedParentNodes.getLength(); i++) {
// create doc from node
Node expectedParentNode = expectedParentNodes.item(i);
Document expectedParentDoc = db.newDocument();
Node importedExpectedNode = expectedParentDoc.importNode(expectedParentNode, true);
expectedParentDoc.appendChild(importedExpectedNode);
boolean hasSimilar = false;
StringBuilder messages = new StringBuilder();
// for each expected parent, find a similar parent
for(int j=0; j < actualParentNodes.getLength(); j++) {
// create doc from node
Node actualParentNode = actualParentNodes.item(j);
Document actualParentDoc = db.newDocument();
Node importedActualNode = actualParentDoc.importNode(actualParentNode, true);
actualParentDoc.appendChild(importedActualNode);
// XMLUnit Diff
Diff diff = new Diff(expectedParentDoc, actualParentDoc);
messages.append(diff.toString());
boolean similar = diff.similar();
if(similar) {
hasSimilar = true;
}
}
// assert it found a similar parent node
assertTrue("expected and actual XML nodes are not equivalent " + messages, hasSimilar);
}