10

我有一个带有ToString生成 XML 的方法的类。我想对其进行单元测试以确保它生成有效的 xml。我有一个 DTD 来验证 XML。

我应该将 DTD 作为字符串包含在单元测试中以避免依赖它,还是有更聪明的方法来做到这一点?

4

3 回答 3

6

如果您的程序在正常执行期间根据 DTD 验证 XML,那么您应该从您的程序获取 DTD 的任何地方获取 DTD。

如果不是并且 DTD 非常短(只有几行),那么将它作为字符串存储在您的代码中可能是可以的。

否则,我会将它放在一个外部文件中,并让您的单元测试从该文件中读取它。

于 2008-09-09T12:49:48.810 回答
6

我过去使用过XmlUnit,发现它很有用。

它可用于根据模式验证 XML 或将您的 XML 与字符串进行比较。理解 XML 的解析规则就足够聪明了。例如,它知道“<e1/>”等价于“<e1></e1>”,并且可以配置为忽略或包含空格。

于 2008-09-09T13:14:38.767 回答
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
    }
}

使用差异监听器:

    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);
于 2015-06-04T14:46:46.173 回答