Java Hamcrest:Collection包含类型的项目

时间:2011-02-13 00:23:51

标签: java unit-testing hamcrest

我想断言List<Achievement>包含TestAchievement类型的成员。

这是我的断言:

List<Achievement> achievements; // Populated elsewhere
assertThat(achievements,hasItem(isA(TestAchievement.class)));

这不编译,报告错误:

  

方法断言(T,Matcher)   在Assert类型中不适用   为参数(List,   匹配&LT;可迭代&LT; TestAchievement&GT;&GT)

使用Hamcrest进行此类断言的正确语法是什么?

7 个答案:

答案 0 :(得分:21)

感谢您的帮助。

这里的帖子暗示这是Hamcrest的一个缺陷,所以我前往hacmrest网站注册一个bug,我发现我使用的mvn / ivy依赖声明是过时的,给了我一个旧版的Hamcrest。

这个错误存在于1.1,这是使用

声明的最新错误
<dependency org="org.hamcrest" name="hamcrest-all" rev="1.1">

但是,正确的依赖声明是:

<dependency org="org.hamcrest" name="hamcrest-library" rev="1.3.RC2"/>

更新到此解决了这个问题。我的测试中使用的语法是:

 assertThat(achievements, hasItem(isA(TestAchievement.class)));

答案 1 :(得分:9)

Java 6中有一个bug与此相关。

此代码会抛出各种错误,例如“找不到符号......”

assertThat(achievements, hasItem(isA(TestAchievement.class)));

解决此问题的方法是将匹配器声明为变量,然后引用该变量。重要的是要注意变量的类型,特别是泛型部分,对于它来说非常重要。

Matcher<Iterable<? super TestAchievement>> matcher = hasItem(isA(TestAchievement.class));
assertThat(achievements, matcher);

有趣的是,如果您使用instanceOf()代替isA(),则会再次遇到问题。 (尽管如果你忽略了警告,这可能对你有用。)扩展你可以使用的上一个修复:

Matcher<TestAchievement> itemMatcher = Matchers.instanceOf(TestAchievement.class);
Matcher<Iterable<? super TestAchievement>> matcher = hasItem(itemMatcher);
assertThat(achievements, matcher);

答案 2 :(得分:3)

assertThat(achievements, hasItem(
    IsInstanceOf.<Achievement>instanceOf(TestAchievement.class)));

答案 3 :(得分:3)

我一直在与此作斗争一段时间,这里的方法都没有真正达到预期效果。出于纯粹的绝望,我尝试转换为数组,看看是否有所作为:

List<Object> listOfThings = (List) someService.findThings(); // your business logic here
Object[] arrayOfThings  = listOfThings.toArray(new Object[listOfThings.size()]);

assertThat(arrayOfThings, hasItemInArray(instanceOf(SpecialThing.class)));

它确实有所作为。现在我的测试完美无瑕。复制到阵列的一行似乎是一个合理的权衡,以节省大量的麻烦。

答案 4 :(得分:2)

我一直在讨论这个问题,似乎我知道的唯一方法是将List<Achievement>转换为List<Object>。问题是CoreMatchers.instanceOf()返回Matcher<Object>

通过这种修改,我能够让它发挥作用: -

List<Object> achievements = new ArrayList<Object>();
achievements.add(new Achievement());
achievements.add(new TestAchievement());
assertThat(achievements, hasItem(instanceOf(TestAchievement.class)));

答案 5 :(得分:2)

来自http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-java/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java,签名是

assertThat(T actual, Matcher<? super T> matcher)

所以问题是你的匹配器是Matcher<TestAchievement>,而不是适用于任何超类或成就接口实例的匹配器。

看起来instanceOf匹配器只有一个错误的类型绑定。 您可以通过执行类似

之类的操作来解决该错误
@SuppressWarnings("unchecked")
Matcher/*no_param*/ isATestAchievement = instanceOf(TestAchievement.class);
assertThat(..., isATestAchievement);

答案 6 :(得分:2)

Actuall它不适用于更复杂的Matcher,即使使用最新版本。

assertThat(result.getAnswers(),
            Matchers.hasItem(Matchers.hasProperty("content")));

它不起作用,你会得到:

  

方法断言Assert类型中的(T,Matcher)不适用于参数(Set,Matcher&gt;)

您可以通过将其转换为数组来解决它:

assertThat(result.getAnswers().toArray(), hasItemInArray(Matchers.hasProperty("content", equalTo("<h4>new comment</h4>"))));