【发布时间】:2010-09-08 06:47:20
【问题描述】:
我有一个带有ToString 方法的类,它可以生成XML。我想对其进行单元测试以确保它生成有效的 xml。我有一个 DTD 来验证 XML。
我应该将 DTD 作为字符串包含在单元测试中以避免对其产生依赖,还是有更聪明的方法来做到这一点?
【问题讨论】:
标签: xml unit-testing language-agnostic dtd
我有一个带有ToString 方法的类,它可以生成XML。我想对其进行单元测试以确保它生成有效的 xml。我有一个 DTD 来验证 XML。
我应该将 DTD 作为字符串包含在单元测试中以避免对其产生依赖,还是有更聪明的方法来做到这一点?
【问题讨论】:
标签: xml unit-testing language-agnostic dtd
在单元测试中使用 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);
【讨论】:
我过去使用过XmlUnit,发现它很有用。
它可用于根据模式验证 XML 或将您的 XML 与字符串进行比较。理解 XML 的解析规则就足够聪明了。
例如,它知道“
【讨论】:
如果您的程序在正常执行期间根据 DTD 验证 XML,那么您应该从您的程序获取 DTD 的任何地方获取它。
如果不是并且 DTD 非常短(只有几行),那么将它作为字符串存储在您的代码中可能是可以的。
否则,我会将其放在外部文件中,并让您的单元测试从该文件中读取它。
【讨论】: