我有一个使用ToString
方法生成XML的类。我想对它进行单元测试,以确保它生成有效的xml。我有一个DTD来验证XML。
我应该在单元测试中将DTD作为字符串包含在内以避免依赖,还是有更智能的方法来执行此操作?
答案 0 :(得分:6)
如果您的程序在正常执行期间针对DTD验证XML,那么您应该从程序获取DTD的任何地方获取DTD。
如果没有并且DTD非常短(只有几行),那么将其作为字符串存储在代码中可能没问题。
否则,我会把它放在一个外部文件中,让你的单元测试从那个文件读取它。
答案 1 :(得分:6)
我过去曾使用XmlUnit并发现它很有用。
它可用于根据模式验证XML或将XML与字符串进行比较。理解XML的解析规则非常聪明。 例如,它知道“< e1 />”相当于“< e1>< / e1>”并且可以配置为忽略或包含空格。
答案 2 :(得分:0)
在单元测试中使用DTD测试其有效性是一回事,测试正确的内容是另一回事。
您可以使用DTD检查生成的xml的有效性,我只是按照您在程序中的方式阅读。我个人不会将其内联(作为字符串);应用程序代码和单元测试之间始终存在依赖关系。当生成的xml发生更改时,DTD也会发生变化。
要测试正确的内容,我会选择XMLUnit。
使用XMLUnit断言xml:
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);
Diff diff = new Diff(expectedDocument, obtainedDocument);
XMLAssert.assertXMLIdentical("xml invalid", diff, true);
您可能遇到的一件事是生成的xml可能包含更改的标识符(id / uid属性或类似)。这可以通过在断言生成的xml时使用DifferenceListener来解决。
此类DifferenceListener的示例实现:
public class IgnoreVariableAttributesDifferenceListener implements DifferenceListener {
private final List<String> IGNORE_ATTRS;
private final boolean ignoreAttributeOrder;
public IgnoreVariableAttributesDifferenceListener(List<String> attributesToIgnore, boolean ignoreAttributeOrder) {
this.IGNORE_ATTRS = attributesToIgnore;
this.ignoreAttributeOrder = ignoreAttributeOrder;
}
@Override
public int differenceFound(Difference difference) {
// for attribute value differences, check for ignored attributes
if (difference.getId() == DifferenceConstants.ATTR_VALUE_ID) {
if (IGNORE_ATTRS.contains(difference.getControlNodeDetail().getNode().getNodeName())) {
return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
// attribute order mismatch (optionally ignored)
else if (difference.getId() == DifferenceConstants.ATTR_SEQUENCE_ID && ignoreAttributeOrder) {
return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
// attribute missing / not expected
else if (difference.getId() == DifferenceConstants.ATTR_NAME_NOT_FOUND_ID) {
if (IGNORE_ATTRS.contains(difference.getTestNodeDetail().getValue())) {
return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return RETURN_ACCEPT_DIFFERENCE;
}
@Override
public void skippedComparison(Node control, Node test) {
// nothing to do
}
}
使用DifferenceListener:
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);
Diff diff = new Diff(expectedDocument, obtainedDocument);
diff.overrideDifferenceListener(new IgnoreVariableAttributesDifferenceListener(Arrays.asList("id", "uid"), true));
XMLAssert.assertXMLIdentical("xml invalid", diff, true);