JUnit ~ Утверждают, что список содержит объекты с одинаковыми значениями в любом порядке - PullRequest
0 голосов
/ 21 февраля 2020

Мой пример использования: я пишу анализатор документов (для документов ReqIF) и хочу сравнить, что анализируемый объект содержит ожидаемые элементы. Для этого я хочу написать JUnit Test.

По сути, я ищу метод утверждения, который сравнивает два списка объектов со значениями и проходит, когда оба списка содержат (в любом порядке) объекты, которые имеют те же значения, что и в списке ссылок.

Чтобы абстрагировать это, рассмотрите этот пример:

Apple referenceApple1 = new Apple(color="red");
Apple referenceApple2 = new Apple(color="green");
Apple parsedApple1 = new Apple(color="red");
Apple parsedApple2 = new Apple(color="green");
Apple badApple = new Apple(color="brown");

List<Apple> referenceList = new List<Apple>(referenceApple1, referenceApple2);
List<Apple> correctlyParsedList1 = new List<Apple>(parsedApple1, parsedApple2);
List<Apple> correctlyParsedList2 = new List<Apple>(parsedApple2, parsedApple1);
List<Apple> wronglyParsedList1 = new List<Apple>(parsedApple1, badApple);
List<Apple> wronglyParsedList2 = new List<Apple>(parsedApple1, parsedApple2, parsedApple1);
List<Apple> wronglyParsedList3 = new List<Apple>(parsedApple2, parsedApple2);

Я ищу метод подтверждения, который проходит при сравнении любого из вышеупомянутых correctlyParsedList* с referenceList, но не удается при сравнении любого из вышеперечисленных wronglyParsedList* с referenceList.

В настоящее время наиболее близким является следующее:

assertEquals(referenceList.toString(), correctlyParsedList1.toString())

Однако , которая завершится ошибкой, как только объекты будут в другом порядке.

//Will fail, but I want a method that will compare these and pass
assertEquals(referenceList.toString(), correctlyParsedList2.toString())

Примечательно, что следующее также не будет выполнено, поскольку яблоки, содержащие одинаковые значения, не являются экземплярами одного и того же объекта:

assertThat(correctlyParsedList1, is(referenceList));

//Throws This error:
java.lang.AssertionError: 
Expected: is <[[color="red"], [color="green"]]>
     but: was <[[color="red"], [color="green"]]>

Есть ли простой способ сделать такое утверждение в JUnit? Я знаю, что мог бы написать собственный метод утверждения для этой итерации по объектам, но почему-то это было бы распространенным случаем, который должен иметь заранее определенный метод подтверждения, который генерирует выразительные ошибки утверждения.


РЕДАКТИРОВАНИЕ ~ КОНКРЕТИЗАЦИЯ

Что я на самом деле пытаюсь сделать с этим абстрактным примером, это проанализировать комплекс XML с использованием JDOM2, и я хочу утверждать, что атрибуты анализируемого тега равны тем, которые существуют в примере документа я даю в качестве ввода. Поскольку это XML, порядок атрибутов не имеет значения, если они имеют правильные значения.

Таким образом, то, что я сравниваю в этом практическом примере использования, равно двум List<Attribute>, с Attribute от org.jdom2.Attribute.

Полный временный тестовый набор, с которым я в данный момент недоволен, потому что он потерпит неудачу, если порядок атрибутов изменится, но не должен быть следующим:

    @Test
    public void importXML_fromFileShouldCreateXML_objectWithCorrectAttributes() throws JDOMException, IOException {
        testInitialization();
        List<Attribute> expectedAttributes = rootNode.getAttributes();

        XML_data generatedXML_data = xml_importer.importXML_fromFile(inputFile);
        List<Attribute> actualAttributes = generatedXML_data.attributes;

        assertEquals(expectedAttributes.toString(), actualAttributes.toString());
    }

Конкретная ошибка, которую я получаю при попытке сделать это утверждение с помощью assertThat(expectedAttributes, is(actualAttributes)):

java.lang.AssertionError: 
Expected: is <[[Attribute: xsi:schemaLocation="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"], [Attribute: xml:lang="en"]]>
    but: was <[[Attribute: xsi:schemaLocation="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"], [Attribute: xml:lang="en"]]>

Ответы [ 2 ]

1 голос
/ 21 февраля 2020

Вы должны использовать containsAll, чтобы проверить, есть ли в одном списке все элементы из другого, если у вас есть правильная реализация равно для вашего Apple, это должно работать:

    // Covers case where all items that are from correct list are in reference as well
    // but also some additional items exist that are not in correct list
    assertEquals(correctlyPassedList.size(), referenceList.size());
    // Checks if each element is contained in list
    assertTrue(referenceList.containsAll(correctlyPassedList));

ОБНОВЛЕНИЕ

Что касается вашего последнего комментария, вероятно, это будет работать лучше всего:

    // Sort both lists using comparator based on id or whatever field is relevant
    referenceList.sort(Comparator.comparingInt(Apple::getId));
    correctlyParsedList.sort(Comparator.comparingInt(Apple::getId));
    // Check if they are equal
    assertEquals(correctlyParsedList, referenceList);
1 голос
/ 21 февраля 2020

Если вам не важен порядок элементов, вы можете отсортировать списки перед их сравнением.

...