我的用例是我正在编写一个文档解析器(用于 ReqIF 文档)并且想要比较解析的对象是否包含预期的元素。 为此,我想编写一个 JUnit 测试。

实际上,我正在寻找的是一种断言方法,该方法将两个对象列表与值进行比较,并在两个列表都包含(以任何顺序)与引用列表具有相同值的对象时通过。

为了抽象,考虑这个例子:

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())

值得注意的是,以下内容也会失败,因为 Apple 虽然包含相同的值,但不是同一对象的实例:

assertThat(correctlyParsedList1, is(referenceList));

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

有没有一种简单的方法可以在 JUnit 中做出这样的断言? 我知道我可以为此迭代对象编写自定义断言方法,但不知何故,感觉这将是一个常见用例,应该有一个预定义的断言方法,该方法会引发表达性断言错误。


编辑~具体化

我实际上试图用这个抽象示例做的是使用 JDOM2 解析一个复杂的 XML,我想断言被解析的标签的属性等于我作为输入提供的示例文档中存在的属性。 由于这是 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"]]>

#1楼 票数:3

您应该使用containsAll来检查一个列表是否containsAll另一个列表中的所有项目,只要您的Apple有适当的 equals 实现,这应该可以工作:

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

#2楼 票数:1

如果你不关心元素的顺序,你可以在比较它们之前对列表进行排序。

#3楼 票数:0

我个人更喜欢始终使用AssertJ

import static org.assertj.core.api.Assertions.assertThat;

这两个断言中的任何一个都应该可以解决问题!

assertThat(correctlyParsedList1).containsOnlyOnce(referenceApple1, referenceApple2);
assertThat(correctlyParsedList1).containsOnlyOnceElementsOf(referenceList);

#4楼 票数:0

根据@FilipRistic 的回答,这对我有用:

使用基于id或任何相关字段的比较器对两个列表进行排序:

referenceList.sort(Comparator.comparingInt(Apple::getId));
correctlyParsedList.sort(Comparator.comparingInt(Apple::getId));

然后简单地:

assertThat(referenceList).usingRecursiveComparison().isEqualTo(correctlyParsedList);

  ask by Kira Resari translate from so

未解决问题?本站智能推荐:

3回复

Junit:断言一个列表包含至少一个与某些条件匹配的属性

我有一个方法将返回MyClass类型的对象列表。 MyClass具有许多属性,但是我关心的是type和count 。 我想编写一个测试,断言返回的列表至少包含一个符合特定条件的元素。 例如,我要在类型"Foo"的列表中至少包含一个元素并计数1 。 我试图弄清楚如何做到这一点,而又不逐字
1回复

如何断言多个变量具有相同的值?

我正在为计算功能编写jUnit测试 如果输入是“翻转”的,则该函数应返回相同的结果,即,先输入哪个无关紧要,无论输入是负还是正(只要它们具有相等的符号)都无关紧要。 以下所有结果都应产生相同的结果: 但这具有当其中一个失败时终止测试方法的缺点。 我当前的测试仅简单地提出了4个断言
13回复

断言等于Junit中的2个列表

如何在JUnit测试用例中的列表之间进行相等断言? 列表的内容之间应该相等。 例如:
1回复

Junit-断言两个相同的数组列表会使测试失败

我正在对一个端点进行测试。 这个端点返回一个对象列表,所以我的测试包括与数组列表的比较。 测试已经在第一个元素中失败了,即使日志显示对象的字段是相同的: org.opentest4j.AssertionFailedError:可迭代内容在索引 [0] 处不同,预期:<Dispatch(dis
1回复

断言该值是在java和testng或junit中的map中设置的

我有一个用java编写的测试,它包含一个发送到服务器的简单HTTP请求,然后捕获服务器响应。 在这里,我想要一种方法来断言我从服务器接收的响应头的控制台输出? 其中一个响应头的示例:如果“Content-Length”= 12227则是一个传递,否则它将失败该测试。 这是我的代码:
1回复

使用AssertJ断言列表中的单个对象

我正在使用 AssertJ 库在我的测试中执行断言。 在这种情况下,我想测试列表中的每个Date对象是否都在其他日期之后。 所以我显然可以做到以下几点: 没有关于它的问题。 但是如果我想测试列表的每个元素以确保它们都在给定日期之后怎么办。 我通过创建自定义org.assertj.core.api.C
3回复

JUnit-如何测试具有不同值的方法?

我有一个方法,并希望用不同的值测试它。 我的问题是:如何编写一个JUnit测试,用不同的值测试相同的方法?
4回复

Junit测试具有双值的hashMap

我正在使用Junit声明在调用方法后收到的预期HashMap与实际HashMap之间的相等性。 代码如下: 这里expectedKlassToScore和klassToScore是类型的Map<MyObject, Double> 。 HashMap中的某些值在小数点后最多16