java-为什么此代码尝试使用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>>>)
ripper234 asked 2019-11-15T10:28:11Z
9个解决方案
53 votes

刚遇到这篇文章试图自己修复它。 给我足够的信息来解决它。

通过将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));

以防万一其他人仍在受苦...

编辑添加:尽管投票赞成,但这个答案是错误的,正如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()])));
Clive Evans answered 2019-11-15T10:28:52Z
22 votes

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

Dan Godfrey answered 2019-11-15T10:29:32Z
12 votes

您正在将ArrayList<T>int进行比较。正确的比较是:

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

-编辑-

对不起,我读错了。 无论如何,您想要的ArrayList<T>的签名是:

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

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

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

-编辑2-

只需在此处粘贴我的评论,就可以在不使用Hamcrest的情况下找到您想要的等效表达:

assertTrue(actual.containsAll(expected));
freitass answered 2019-11-15T10:30:33Z
3 votes

尝试

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

满足匹配者签名。 没有Eclipse,所以这可能行不通。

Robert Munteanu answered 2019-11-15T10:30:59Z
2 votes

该错误消息看起来像是javac编译器产生的错误消息。 我过去发现使用hamcrest编写的代码不会在javac下编译。 相同的代码可以在Eclipse编译器下很好地编译。

我认为Hamcrest的泛型正在javac无法处理的泛型中执行极端情况。

skaffman answered 2019-11-15T10:31:31Z
2 votes

我遇到了同样的问题,以下技巧对我有用:

  • 使用import static org.hamcrest.Matchers.hasItems
  • 在classpath中的junit之前拥有hamcrest库(构建路径->命令并导出)
Zsolt answered 2019-11-15T10:32:11Z
2 votes

如果尝试用较新的版本替换jUnit的hamcrest,则会出现此错误。 例如,将junit-dep与hamcrest 1.3一起使用要求使用hamcrest中的assertThat而不是jUnit。

所以解决方案是使用

import static org.junit.Assert.assertThat;

代替

import static org.junit.Assert.assertThat;

Mika answered 2019-11-15T10:32:54Z
1 votes

对于这些情况,当代码确实在Eclipse中编译但Javac显示错误时,请通过提供明确的类型参数来帮助解决问题。Matchers.hasItem()

miluch answered 2019-11-15T10:33:20Z
0 votes
ArrayList<Integer> expected = new ArrayList<Integer>();
expected.add(1);
expected.add(2);
hasItems(expected);

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

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

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

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

它将扩展为:

hasItems(1, 2);
Matthew answered 2019-11-15T10:34:02Z
translate from https://stackoverflow.com:/questions/1092981/why-doesnt-this-code-attempting-to-use-hamcrests-hasitems-compile