【问题标题】:XMLUnit nested element testingXMLUnit 嵌套元素测试
【发布时间】:2016-12-20 21:17:18
【问题描述】:

我有两个要比较的 XML 文件。我正在使用 XMLUnit 2。但是元素可能是无序的(包括子元素排序)下面所有三个示例都需要被视为等效:

<Product>
    <Property>
        <Container value="1">Test 01</Container>
        <Container value="3">Test 02</Container>
        <Container value="5">Test 03</Container>
    </Property>
    <Property>
        <Container value="2">Test A</Container>
        <Container value="4">Test B</Container>
        <Container value="6">Test C</Container>
    </Property>
</Product>

<Product>
    <Property>
        <Container value="5">Test 03</Container>
        <Container value="1">Test 01</Container>
        <Container value="3">Test 02</Container>
    </Property>
    <Property>
        <Container value="2">Test A</Container>
        <Container value="4">Test B</Container>
        <Container value="6">Test C</Container>
    </Property>

<Product>
    <Property>
        <Container value="2">Test A</Container>
        <Container value="4">Test B</Container>
        <Container value="6">Test C</Container>
    </Property>
    <Property>
        <Container value="5">Test 03</Container>
        <Container value="1">Test 01</Container>
        <Container value="3">Test 02</Container>
    </Property>
</Product>

似乎 XMLUnit 应该能够相当容易地做到这一点,但我不知道我需要做什么来配置测试。我应该补充一点,如果容器下面有更多元素可以证明相同的问题,那么嵌套可以变得更深。

---

可能的解决方案:

public class SubNodeEqualityElementSelector implements ElementSelector {

    public SubNodeEqualityElementSelector() {

    }

    @Override
    public boolean canBeCompared(Element controlElement, Element testElement) {
        // test input nodes for equality first.
        if (!ElementSelectors.byNameAndAllAttributes.canBeCompared(controlElement, testElement)) {
            return false;
        }
        if (!ElementSelectors.byNameAndText.canBeCompared(controlElement, testElement)) {
            return false;
        }

        // test children for equality.  For each ctrl child, make sure that a matching element is found in the test set.
        ArrayList<Element> ctrlChildren = getChildElements(controlElement);
        ArrayList<Element> testChildren = getChildElements(testElement);
        ArrayList<Element> ctrlChildrenResults = new ArrayList<Element>(ctrlChildren);
        ArrayList<Element> testChildrenResults = new ArrayList<Element>(testChildren);

        for (Element ctrlChild : ctrlChildren) {
            for (Element testChild : testChildren) {
                if (ElementSelectors.byNameAndAllAttributes.canBeCompared(ctrlChild, testChild) &&
                        ElementSelectors.byNameAndText.canBeCompared(ctrlChild, testChild)) {
                    ctrlChildrenResults.remove(ctrlChild);
                    testChildrenResults.remove(testChild);
                }
            }
        }

        return ctrlChildrenResults.size() == 0 && testChildrenResults.size() == 0;
    }

    private ArrayList<Element> getChildElements(Element elem) {
        ArrayList<Element> retVal = new ArrayList<Element>();

        NodeList childNodes = elem.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            if (node instanceof Element){
                Element element = (Element) node;
                retVal.add(element);
            }
        }

        return retVal;
    }

}

我测试了上面的类(SubNodeEqualityElementSelector),它似乎运行良好!

【问题讨论】:

    标签: java junit xmlunit


    【解决方案1】:

    这是一个相当困难的例子。

    如果您想用 XMLUnit 1.x 解决这个问题,那么您必须编写一个 ElementQualifier 代码,以便在面对列表时选择正确的 Property 元素。您必须自己编写,内置版本都不会。此外,您只能拥有一个 ElementQualifier,因此您还需要处理剩余的比较,例如选择正确的 Container - ElementNameAndAttributeQualifier 可以做到这一点。

    使用 XMLUnit 2.x 并没有变得容易很多,但至少您可以使用条件生成器来组合 ElementSelectorhttps://github.com/xmlunit/user-guide/wiki/SelectingNodes 中的用户指南示例很接近,它根据第一个“内部”元素的嵌套文本选择正确的“外部”元素。在您的情况下,您似乎需要根据嵌套的Containers 的属性选择Property,但不幸的是,仅查看第一个Container 是不够的。恐怕我们不会想出一个有效的 XPath,所以你可能仍然需要编写 Java 代码来选择正确的 Property,但是一旦你有了它,你就可以做类似的事情

    ElementSelectors.conditionalBuilder()
        .whenElementIsNamed("Property").thenUse(YOUR_ELEMENT_SELECTOR)
        .elseUse(ElementSelectors.byNameAndAllAttributes)
        .build();
    

    【讨论】:

    • 我写了这个,到目前为止它正在工作。我需要坐在调试器中尝试一下。谢谢你给我的起点。
    • 查看我编辑的原始帖子,了解似乎是一个有效的比较器。
    猜你喜欢
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 2017-06-15
    • 2020-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多