【发布时间】:2011-01-19 18:31:16
【问题描述】:
您将如何简洁地断言 Collection 元素的相等性,特别是 JUnit 4 中的 Set?
【问题讨论】:
-
您是要断言两个 Set 彼此相等(包含相同的元素),还是同一 Set 的两个元素相等?
-
我要看看两个Set的元素是否相等
标签: java unit-testing collections junit
您将如何简洁地断言 Collection 元素的相等性,特别是 JUnit 4 中的 Set?
【问题讨论】:
标签: java unit-testing collections junit
您可以断言两个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 将通过。
【讨论】:
equals 和 hashCode?
Apache commons 再次出手相救。
assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));
像魅力一样工作。我不知道为什么,但我发现以下assertEquals(coll1, coll2) 的集合并不总是有效。在我失败的情况下,我有两个由 Sets 支持的集合。 hamcrest 和 junit 都不会说这些系列是平等的,尽管我确定它们是平等的。使用 CollectionUtils 可以完美运行。
【讨论】:
【讨论】:
一个特别有趣的例子是当你比较时
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()));
或者我可以逐个元素地比较它们。
【讨论】:
作为基于数组的附加方法...您可以考虑在 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"/>
【讨论】:
检查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);
}
【讨论】:
使用 Hamcrest:
assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));
这也适用于集合具有不同数据类型的情况,并报告差异而不是仅仅失败。
【讨论】:
我喜欢 Hans-Peter Störr 的解决方案……但我认为它并不完全正确。可悲的是containsInAnyOrder 不接受要比较的对象的Collection。所以它必须是Collection 的Matchers:
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;
【讨论】:
如果要检查 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”区分开来。但在实践中我认为最重要的是它的简单和快速编写测试,否则许多开发人员不会不被按下。)
【讨论】: