XMLUnit — проблема сравнения с XML-файлами, которые находятся в другом порядке

Я использую XMLUnit2 для сравнения двух XML-файлов, которые не имеют элементов в том же порядке. Я вижу следующую ошибку -

Различия = Ожидаемый дочерний 'billingCode', но был 'null' - сравнение в /translateServiceRequestResponse[1]/translateServiceRequestReturn[1]/legacyCode[2]/billingCode[1] с NULL

Код

Diff myDiff = DiffBuilder.compare(controlResponse).ignoreWhitespace().ignoreComments().withTest(testResponse).withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)).checkForSimilar().build();
System.out.println("Differences = " + myDiff.toString());

Контрольный файл

<translateServiceRequestResponse>
<translateServiceRequestReturn>
    <legacyCode>
        <amount>0</amount>
        <billingCode>VS128</billingCode>
        <description>HD Rec</description>
        <priceName>EquipChoice X1 HD TP</priceName>
        <pricingElementName>X1 HD Receiver</pricingElementName>
        <codeAmount>0</codeAmount>
        <lobSubType>0</lobSubType>
        <addressable>1</addressable>
        <nonStandard>false</nonStandard>
    </legacyCode>
    <legacyCode>
        <amount>0</amount>
        <billingCode>VF123</billingCode>
        <description>HD Rec</description>
        <packageCode>VE286</packageCode>
        <priceName>EquipChoice X1 HD TP</priceName>
        <pricingElementName>X1 HD Receiver</pricingElementName>
        <codeAmount>0</codeAmount>
        <lobSubType>0</lobSubType>
        <addressable>1</addressable>
        <nonStandard>false</nonStandard>
    </legacyCode>
    <legacyCode>
        <amount>0</amount>
        <billingCode>VF170</billingCode>
        <description>HD Rec</description>
        <packageCode>VE286</packageCode>
        <priceName>EquipChoice X1 HD TP</priceName>
        <pricingElementName>X1 HD Receiver</pricingElementName>
        <codeAmount>2.5</codeAmount>
        <lobSubType>0</lobSubType>
        <addressable>1</addressable>
        <nonStandard>false</nonStandard>
    </legacyCode>
</translateServiceRequestReturn>

Test File

<translateServiceRequestResponse>
<translateServiceRequestReturn>
    <legacyCode>
        <amount>0</amount>
        <billingCode>VS128</billingCode>
        <description>HD Rec</description>
        <priceName>EquipChoice X1 HD TP</priceName>
        <pricingElementName>X1 HD Receiver</pricingElementName>
        <codeAmount>0</codeAmount>
        <lobSubType>0</lobSubType>
        <addressable>1</addressable>
        <nonStandard>false</nonStandard>
    </legacyCode>
    <legacyCode>
        <amount>0</amount>
        <billingCode>VF170</billingCode>
        <description>HD Rec</description>
        <packageCode>VE286</packageCode>
        <priceName>EquipChoice X1 HD TP</priceName>
        <pricingElementName>X1 HD Receiver</pricingElementName>
        <codeAmount>2.5</codeAmount>
        <lobSubType>0</lobSubType>
        <addressable>1</addressable>
        <nonStandard>false</nonStandard>
    </legacyCode>
    <legacyCode>
        <amount>0</amount>
        <billingCode>VF123</billingCode>
        <description>HD Rec</description>
        <packageCode>VE286</packageCode>
        <priceName>EquipChoice X1 HD TP</priceName>
        <pricingElementName>X1 HD Receiver</pricingElementName>
        <codeAmount>0</codeAmount>
        <lobSubType>0</lobSubType>
        <addressable>1</addressable>
        <nonStandard>false</nonStandard>
    </legacyCode>
</translateServiceRequestReturn>


person Punter Vicky    schedule 19.05.2017    source источник


Ответы (1)


XMLUnit использует ElementSelector, чтобы определить, какие элементы двух наборов одноуровневых элементов в контрольном и тестовом документах должны совпадать друг с другом. Он начнет сопоставление с корня документов, и вы должны убедиться, что он выбирает правильные ветви на каждом уровне. Как только решение принято, XMLUnit не отступает.

При выборе ElementSelector вы всегда должны убедиться, что это помогает XMLUnit выбрать правильную ветвь как можно ближе к корню документа, как того требует логическая структура вашего документа. Элементы, которые, как вы говорите, расположены не в том же порядке, являются элементами legacyCode, поэтому вы должны помочь XMLUnit сделать правильный выбор среди них. byNameAndText здесь не поможет. В byNameAndText вообще нет вложенного текста, поэтому все они одинаковы, и XMLUnit сопоставляет элементы в порядке документа.

Это точно такая же проблема, как и проблема с trs в https://github.com/xmunit/user-guide/wiki/SelectingNodes

Мне кажется, что ваш legacyCode будет идентифицирован текстом, вложенным в элемент billingCode. Если это так, вы можете использовать ElementSelector как

ElementSelectors.conditionalBuilder()
    .whenElementIsNamed("legacyCode").thenUse(ElementSelectors.byXPath("./billingCode", ElementSelectors.byNameAndText))
    .elseUse(ElementSelectors.byName)
    .build();

Возможно, вам придется адаптировать это, чтобы оно работало для тех частей документа, которые вы не показывали, или если действительно требуется byNameAndText, а не byName для некоторых других частей дерева.

person Stefan Bodewig    schedule 20.05.2017
comment
Спасибо, Стефан. У меня есть ряд элементов, похожих на legacyCode, перечисленных здесь. Должен ли я указывать каждого из них по имени или есть общий способ сформулировать это. Ценю вашу помощь! - person Punter Vicky; 22.05.2017
comment
Рядом с whenElementIsNamed также есть when, который принимает Predicate<Node>. Если вы можете указать правило, которое выбирает все ваши элементы, вы можете использовать его. - person Stefan Bodewig; 22.05.2017
comment
Еще раз спасибо, Стефан. Можно ли привести пример? - person Punter Vicky; 22.05.2017
comment
Зависит от того, что общего у ваших элементов. Предположим, у вас есть набор имен элементов NAMES и вы можете сделать что-то вроде ElementSelectors.conditionalBuilder().when(e -> NAMES.contains(Nodes.getQName(e).getLocalPart())).thenUse(...). Если вам всегда нужно искать другой дочерний элемент, то вам, вероятно, придется явно указать все элементы и дочерние элементы. - person Stefan Bodewig; 23.05.2017