【问题标题】:JUnit 4 compare SetsJUnit 4 比较集
【发布时间】:2011-01-19 18:31:16
【问题描述】:

您将如何简洁地断言 Collection 元素的相等性,特别是 JUnit 4 中的 Set

【问题讨论】:

标签: java unit-testing collections junit


【解决方案1】:

您可以断言两个Sets 彼此相等,这会调用Set equals() method

public class SimpleTest {

    private Set<String> setA;
    private Set<String> setB;

    @Before
    public void setUp() {
        setA = new HashSet<String>();
        setA.add("Testing...");
        setB = new HashSet<String>();
        setB.add("Testing...");
    }

    @Test
    public void testEqualSets() {
        assertEquals( setA, setB );
    }
}

如果两个Sets 大小相同且包含相同元素,则此@Test 将通过。

【讨论】:

  • 这不会在报告中显示很好的结果。如果你的 toStrings 被明确定义,那就更好了,但仍然不好(一个小的差异可能会以一页文本结束)
  • 嗯,我怎么会得到:java.lang.AssertionError:预期:java.util.Hashtable 但是: java.util.Hashtable
  • @Giodude 您是否在您存储在 Hashtable 中的类中实现了 equalshashCode
  • 如您所见,这些只是字符串和很长的...我正在测试 Avro 以对地图进行序列化和反序列化,这就是结果。我认为字符串序列化和反序列化的方式一定有问题,导致测试失败,但我似乎找不到问题。
  • 对我不起作用,即使我在比较两个 HashSet。 @MattFriedman 的回答实际上适用于我的用例。
【解决方案2】:

Apache commons 再次出手相救。

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));

像魅力一样工作。我不知道为什么,但我发现以下assertEquals(coll1, coll2) 的集合并不总是有效。在我失败的情况下,我有两个由 Sets 支持的集合。 hamcrest 和 junit 都不会说这些系列是平等的,尽管我确定它们是平等的。使用 CollectionUtils 可以完美运行。

【讨论】:

  • 这其实是微不足道的,棘手的部分是要清楚地向调用者表明区别
  • 接受的答案是原始问题的一个很好的答案(专门针对两个集合的单元测试),但我认为 CollectionUtils 的这个答案对于最一般的情况来说是一个更好的答案。除非使用 CollectionUtils,否则我无法比较 Collection 和 Set。
【解决方案3】:

hamcrest:

assertThat(s1, is(s2));

使用简单的断言:

assertEquals(s1, s2);

注意:使用了具体集合类的equals()方法

【讨论】:

  • 我更喜欢这种方法,因为 Hamcrest 带有 JUnit 4,所以不需要其他库。
  • 当集合具有不同类型时,这可能不起作用。
【解决方案4】:

一个特别有趣的例子是当你比较时

   java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

   java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>

到目前为止,我看到的唯一解决方案是将它们都更改为集合

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));

或者我可以逐个元素地比较它们。

【讨论】:

  • 实际上,其他答案中有几种解决方案。无论如何,集合对此有点不幸,因为它们忽略了顺序。也许是 ArrayList?
【解决方案5】:

作为基于数组的附加方法...您可以考虑在 junitx 中使用无序数组断言。虽然 Apache CollectionUtils 示例可以工作,但那里也有一个可靠的断言扩展包:

我认为

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});

方法对您来说更具可读性和可调试性(所有集合都支持 toArray(),因此使用 ArrayAssert 方法应该很容易。

当然这里的缺点是,junitx 是一个额外的 jar 文件或 maven 入口...

 <dependency org="junit-addons" name="junit-addons" rev="1.4"/>

【讨论】:

    【解决方案6】:

    检查this article。一个例子:

    @Test  
    public void listEquality() {  
        List<Integer> expected = new ArrayList<Integer>();  
        expected.add(5);  
    
        List<Integer> actual = new ArrayList<Integer>();  
        actual.add(5);  
    
        assertEquals(expected, actual);  
    }  
    

    【讨论】:

    • 简短但很棒的链接,非常快速地解释了您可以使用 Junit4 做什么-
    • 链接已损坏。您是否有机会在网上找到存档版本或总结其内容?
    【解决方案7】:

    使用 Hamcrest:

    assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));
    

    这也适用于集合具有不同数据类型的情况,并报告差异而不是仅仅失败。

    【讨论】:

    • isIn 的导入是什么? IntelliJ 无法使用任何 hamcret 包解析导入。
    【解决方案8】:

    我喜欢 Hans-Peter Störr 的解决方案……但我认为它并不完全正确。可悲的是containsInAnyOrder 不接受要比较的对象的Collection。所以它必须是CollectionMatchers:

    assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))
    

    导入是:

    import static java.util.stream.Collectors.toList;
    import static org.hamcrest.Matchers.containsInAnyOrder;
    import static org.junit.Assert.assertThat;
    

    【讨论】:

      【解决方案9】:

      如果要检查 List 或 Set 是否包含一组特定值(而不是将其与已经存在的集合进行比较),通常集合的 toString 方法很方便:

      String[] actualResult = calltestedmethod();
      assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());
      
      List otherResult = callothertestedmethod();
      assertEquals("[42, mice]", otherResult.toString());
      

      这比首先构造期望的集合并与实际集合进行比较要短一些,并且更容易编写和更正。

      (诚然,这不是一个特别干净的方法,并且无法将元素“foo,bar”与两个元素“foo”和“bar”区分开来。但在实践中我认为最重要的是它的简单和快速编写测试,否则许多开发人员不会不被按下。)

      【讨论】:

      • 这使得你的单元测试的结果依赖于列表中 toString 的实现。如果他们决定更改格式,则单元测试将不再起作用。我不认为这是安全的。
      • @LaurensOp'tZandt 你的意思是甲骨文改变了 Collection.toList() 的格式?这肯定不会发生。但是,您是对的,这并不是特别干净。但在实践中,我的印象是编写测试非常容易。
      • 我同意,我认为 toString 方法不太可能。所以它可能会继续工作。我只是想指出这不是一种非常干净的方式。但确实很容易。出现的一个问题是比较集合时。因为他们的订单没有保证。
      猜你喜欢
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多