为什么这段代码没有尝试使用Hamcrest的hasItems编译?

时间:2009-07-07 15:22:55

标签: java unit-testing junit hamcrest matcher

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

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

9 个答案:

答案 0 :(得分:53)

试着为自己解决这个问题。给了我足够的信息来解决它。

您可以通过将hasItems的返回值转换为(原始)匹配器来使编译器足以说服它编译,例如:

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

答案 1 :(得分:22)

hasItems检查集合是否包含某些项,而不是2个集合相等,只需使用正常的相等断言即可。所以要么是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));

或者,使用contains Matcher,它检查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

答案 2 :(得分:12)

您正在将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 -

在这里粘贴我的评论,没有使用Hamcrest,你可以使用相同的表达式:

assertTrue(actual.containsAll(expected));

答案 3 :(得分:3)

尝试

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

满足匹配器签名。没有Eclipse,所以这可能不起作用。

答案 4 :(得分:2)

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

我认为Hamcrest的仿制药正在使用javac无法处理的泛型中的角落案例。

答案 5 :(得分:2)

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

  • 使用import static org.hamcrest.Matchers.hasItems
  • 在classpath中的junit之前有hamcrest库(构建路径 - &gt; order and export)

答案 6 :(得分:2)

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

所以解决方案是使用

import static org.hamcrest.MatcherAssert.assertThat;

而不是

import static org.junit.Assert.assertThat;

答案 7 :(得分:1)

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

答案 8 :(得分:0)

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