为什么这段代码不试图使用Hamcrest的hasItems进行编译?

为什么这不能编译,哦,该怎么办?

import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.hasItems; ArrayList<Integer> actual = new ArrayList<Integer>(); ArrayList<Integer> expected = new ArrayList<Integer>(); actual.add(1); expected.add(2); assertThat(actual, hasItems(expected)); 

错误从评论复制:

 cannot find symbol method assertThat(java.util.ArrayList<java.lang.Integer>, org.hamcreset.Matcher<java.lang.Iterable<java.util.ArrayList<java.lang.Integer>>>) 

刚刚遇到这个post试图自己修复它。 给我足够的信息来解决这个问题。

你可以给编译器足够的说服,通过将hasItems的返回值转换成一个(原始的)Matcher来编译它,例如:

 ArrayList<Integer> actual = new ArrayList<Integer>(); ArrayList<Integer> expected = new ArrayList<Integer>(); actual.add(1); expected.add(2); assertThat(actual, (Matcher) hasItems(expected)); 

以防其他人仍然受苦

编辑添加:尽pipe赞成票,这个答案是错误的,正如Arend指出的那样。 正确的答案是把期望变成一个整数数组,正如Hamcrest所期待的那样:

  ArrayList<Integer> actual = new ArrayList<Integer>(); ArrayList<Integer> expected = new ArrayList<Integer>(); actual.add(1); expected.add(2); assertThat(actual, hasItems(expected.toArray(new Integer[expected.size()]))); 

hasItems检查集合是否包含一些项目,而不是两个集合是相等的,只是使用普通的相等断言。 所以要么assertEquals(a,b)要么使用assertThat

 import static org.junit.Assert.assertThat; import static org.hamcrest.CoreMatchers.is; ArrayList<Integer> actual = new ArrayList<Integer>(); ArrayList<Integer> expected = new ArrayList<Integer>(); actual.add(1); expected.add(2); assertThat(actual, is(expected)); 

或者,使用包含匹配器,它将检查Iterable是否包含特定顺序的项目

 import static org.junit.Assert.assertThat; import static org.hamcrest.Matchers.contains; ArrayList<Integer> actual = new ArrayList<Integer>(); actual.add(1); actual.add(2); assertThat(actual, contains(1, 2)); // passes assertThat(actual, contains(3, 4)); // fails 

如果您不关心订单,请改用containsInAnyOrder

您正在比较ArrayList<Integer>int 。 正确的比较是:

 ... assertThat(actual, hasItem(2)); 

– 编辑 –

对不起,我读错了。 无论如何,你想要的hasItems的签名是:

 public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... elements) 

即它接受可变数目的参数。 我不确定一个ArrayList<T>是否兼容,只是在这里猜测。 尝试从逗号分隔的预期列表中发送每个项目。

 assertThat(actual, hasItems(2,4,1,5,6)); 

– 编辑2 –

只是在这里粘贴我的评论,有一个相同的expression式,你想要什么,而不使用Hamcrest:

 assertTrue(actual.containsAll(expected)); 

尝试

 assertThat(actual, hasItems(expected.toArray(new Integer[0]))); 

以满足匹配签名。 没有周围的Eclipse,所以这可能无法正常工作。

该错误消息看起来像由javac编译器生成的。 我发现过去用hamcrest编写的代码不会在javac下编译。 在Eclipse编译器下,相同的代码会很好的编译。

我认为Hamcrest的generics正在使用javac无法处理的generics中的angular落案例。

我刚刚遇到同样的问题,下面的技巧为我工作:

  • 使用import static org.hamcrest.Matchers.hasItems
  • 在classpath中有junit的库(build path – > order and export)

你可以得到这个错误,如果你试图用一个更新的版本replacejUnit的hamcrest。 例如,将junit-dep和hamcrest 1.3一起使用需要使用来自hamcrest而不是jUnit的assert。

所以解决的办法是使用

import static org.hamcrest.MatcherAssert.assertThat;

代替

import static org.junit.Assert.assertThat;

对于这些情况下,当代码在Eclipse中编译但javac显示错误,请帮助hamcrest通过提供明确的types参数,例如Matchers.hasItem()

 ArrayList<Integer> expected = new ArrayList<Integer>(); expected.add(1); expected.add(2); hasItems(expected); 

hasItems(T..t)被编译器扩展为:

 hasItems(new ArrayList<Integer>[]{expected}); 

您正在传递包含ArrayList的单个元素数组。 如果将ArrayList更改为数组,则代码将工作。

 Integer[] expected = new Integer[]{1, 2}; hasItems(expected); 

这将被扩展到:

 hasItems(1, 2);