The best way to validate XML in a unit test?

不问归期 提交于 2019-12-06 23:29:24

问题


I have a class with a ToString method that produces XML. I want to unit test it to ensure it is producing valid xml. I have a DTD to validate the XML against.

Should I include the DTD as a string within the unit test to avoid a dependency on it, or is there a smarter way to do this?


回答1:


If your program validates the XML against the DTD during normal execution, then you should just get the DTD from wherever your program will get it.

If not and the DTD is extremely short (only a few lines), then storing it as a string in your code is probably okay.

Otherwise, I'd put it in an external file and have your unit test read it from that file.




回答2:


I've used XmlUnit in the past and found it to be useful.

It can be used to validate XML against a schema or compare your XML against a string. It is clever enough to understand XML's parsing rules. For example it knows that "<e1/>" is equivalent to "<e1></e1>" and can be configured to ignore or include whitespace.




回答3:


Using a DTD in the unit test to test its validity is one thing, testing for the correct content is another.

You can use the DTD to check for the validity of the generated xml which I would simply read the way you do in your program. I personally would not include it inline (as a String); there is always a dependency between you application code and the unit test. When the generated xml changes, the DTD will also change.

To test for the correct content I would go for XMLUnit.

Asserting xml using XMLUnit:

XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);

Diff diff = new Diff(expectedDocument, obtainedDocument);
XMLAssert.assertXMLIdentical("xml invalid", diff, true);

One thing you might come across is the fact that the generated xml might contain changing identifiers (id/uid attributes or alike). This can be solved by using a DifferenceListener when asserting the generated xml.

Example implementation of such 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
    }
}

using 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);


来源:https://stackoverflow.com/questions/51771/the-best-way-to-validate-xml-in-a-unit-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!