2016-01-22 2 views
2

Прежде всего, спасибо за эту замечательную библиотеку, это действительно здорово.XMLUnit 2.0 - Невозможно избежать сравнения заказов с пользовательским селектором элементов

У меня возникла проблема сравнения элементов в другом порядке в моем документе xml. Я разработал пользовательский ElementSelector для использования с NodeMatcher (позже код), но все же он, похоже, проверяет на основе порядка элементов больше, чем содержимое элемента. Позвольте мне написать пример

управления

<Parent> 
<Person> 
<FirstName>John</FirstName> 
<LastName>Doe</LastName> 
<Email>[email protected]</Email> 
</Person> 
<Person> 
<FirstName>Mickey</FirstName> 
<LastName>Mouse</LastName> 
<Email>[email protected]</Email> 
</Person> 
<Person> 
<FirstName>John</FirstName> 
<LastName>Doe</LastName> 
<Email /> 
</Person> 
</Parent> 

Тест

<Parent> 
<Person> 
<FirstName>Mickey</FirstName> 
<LastName>Mouse</LastName> 
<Email>[email protected]</Email> 
</Person> 
<Person> 
<FirstName>John</FirstName> 
<LastName>Doe</LastName> 
<Email>[email protected]</Email> 
</Person> 
<Person> 
<FirstName>John</FirstName> 
<LastName>Doe</LastName> 
<Email /> 
</Person> 
</Parent> 

Как я сделал Diff

Diff diff = DiffBuilder.compare(refSource) 
         .withTest(testSource) 
         .checkForSimilar() 
         .ignoreWhitespace() 
         .normalizeWhitespace() 
         .withNodeMatcher(new DefaultNodeMatcher(selector)) 
         .build(); 

Как я создал селектор ElementSelector

ElementSelector selector = ElementSelectors.conditionalBuilder() 
         .whenElementIsNamed("Person").thenUse(new PersonNodeMatcher()) 
         .defaultTo(ElementSelectors.byNameAndText).build(); 

Как на самом деле реализован PersonNodeMatcher

public class PersonNodeMatcher extends BaseElementSelector { 

@Override 
protected boolean canBeCompared(Element control, Element test) { 

    String controlFirstName = control.getElementsByTagName("FirstName").item(0).getTextContent(); 
    String controlLastName = control.getElementsByTagName("LastName").item(0).getTextContent(); 

    Node controlEmailNode = control.getElementsByTagName("Email").item(0); 
    String controlEmail = null; 
    if (controlEmailNode != null) { 
     controlEmail = controlEmailNode.getTextContent(); 
    } 


    String testFirstName = test.getElementsByTagName("FirstName").item(0).getTextContent(); 
    String testLastName = test.getElementsByTagName("LastName").item(0).getTextContent(); 


    Node testEmailNode = test.getElementsByTagName("Email").item(0); 
    String testEmail = null; 
    if (testEmailNode != null) { 
     testEmail = testEmailNode.getTextContent(); 
    } 

    return bothNullOrEqual(controlFirstName,testFirstName) && 
       bothNullOrEqual(controlLastName,testLastName) && 
       bothNullOrEqual(controlEmail,testEmail); 

} 

Процедура по-прежнему проверять узлы в порядке, так что они никогда не будут соответствовать. Я думал, что предоставление узлового узла узлового узла я мог бы проверить все элементы с предоставленным именем tagName.

Я делаю что-то неправильно или просто невозможно?

[UPDATE] Использование alpha3 я должен был сделать некоторые изменения в коде, а именно:

ElementSelector selector = ElementSelectors.conditionalBuilder() 
         .whenElementIsNamed("Person").thenUse(new PersonNodeMatcher()).build(); 


    Diff diff = DiffBuilder.compare(refSource) 
         .withTest(testSource) 
         .checkForSimilar() 
         .ignoreWhitespace() 
         .normalizeWhitespace() 
         .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.or(selector,ElementSelectors.Default))) 
         .build(); 
+0

какая альфа XMLUnit 2 вы используете? Это может быть реализация conditionalBuilder до alpha3 - https: // github.com/xmlunit/xmlunit/issues/40 –

+0

Я использовал alpha2, теперь я пытаюсь использовать alpha3 – Kerruba

+0

[Update]. Аналогичная проблема с alpha3 кажется неспособной выбрать правильный элемент управления. – Kerruba

ответ

0
  1. я переехал в последней альфа, альфа-03. Возникла проблема с альфа-02;
  2. Вместо использования ElementSelectors.or внутренней части DefaultNodeMatcher, я использовал varargs конструктор

    Diff diff = DiffBuilder.compare(refSource) 
             .withTest(testSource) 
             .checkForSimilar() 
             .ignoreWhitespace() 
             .normalizeWhitespace() 
             .withNodeMatcher(
              new DefaultNodeMatcher(
                selector,ElementSelectors.Default) 
             ) 
             .build(); 
    

    Разница между этими двумя подходами объясняется here.

  3. Это решило мою основную проблему, все еще возникла проблема, так как DifferenceEvaluator выводил этот документ по-разному из-за this (см. Конец абзаца). Действительно, документ SIMILAR, а не IDENTICAL, так как порядок внутренних элементов не равен. Для предотвращения такого выхода из DifferenceEvaluator, в данный момент я обновил DiffBuilder с конкретным DifferenceEvaluator

    .withDifferenceEvaluator(((comparison, outcome) -> { 
        if (outcome == ComparisonResult.DIFFERENT && 
         comparison.getType() == ComparisonType.CHILD_NODELIST_SEQUENCE) { 
          return ComparisonResult.EQUAL; 
        } 
    
        return outcome; 
    })) 
    

    даже если, вероятно, лучшим решением, как это было предложено Stefan Bodewig, будет chain моей реализация с DifferenceListeners.Default и прекратите проверку результатов.

Смежные вопросы