【问题标题】:The best way to validate XML in a unit test?在单元测试中验证 XML 的最佳方法是什么?
【发布时间】:2010-09-08 06:47:20
【问题描述】:

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

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

【问题讨论】:

    标签: xml unit-testing language-agnostic dtd


    【解决方案1】:

    在单元测试中使用 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);
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 感谢 XmlUnit 链接,听起来很有趣且很有帮助
      【解决方案3】:

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

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

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

      【讨论】:

      • DTD 应该存储在本地,因此单元测试不依赖于可用的网络服务。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2012-05-22
      • 2019-02-12
      • 2018-08-22
      • 2016-01-16
      相关资源
      最近更新 更多