我有一个带有ToString
生成 XML 的方法的类。我想对其进行单元测试以确保它生成有效的 xml。我有一个 DTD 来验证 XML。
我应该将 DTD 作为字符串包含在单元测试中以避免依赖它,还是有更聪明的方法来做到这一点?
我有一个带有ToString
生成 XML 的方法的类。我想对其进行单元测试以确保它生成有效的 xml。我有一个 DTD 来验证 XML。
我应该将 DTD 作为字符串包含在单元测试中以避免依赖它,还是有更聪明的方法来做到这一点?
如果您的程序在正常执行期间根据 DTD 验证 XML,那么您应该从您的程序获取 DTD 的任何地方获取 DTD。
如果不是并且 DTD 非常短(只有几行),那么将它作为字符串存储在您的代码中可能是可以的。
否则,我会将它放在一个外部文件中,并让您的单元测试从该文件中读取它。
我过去使用过XmlUnit,发现它很有用。
它可用于根据模式验证 XML 或将您的 XML 与字符串进行比较。理解 XML 的解析规则就足够聪明了。例如,它知道“<e1/>”等价于“<e1></e1>”,并且可以配置为忽略或包含空格。
在单元测试中使用 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
}
}
使用差异监听器:
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);