21

我想断言List<Achievement>包含 type 的成员TestAchievement

这是我的断言:

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

这不编译,报告错误:

Assert 类型中的方法 assertThat(T, Matcher) 不适用于参数 (List, Matcher<Iterable<TestAchievement>>)

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

4

7 回答 7

22

感谢所有的帮助。

这里的帖子表明这是 Hamcrest 的一个缺陷,所以当我发现我使用的 mvn / ivy 依赖声明已过期时,我前往 hacmrest 站点注册了一个错误,给了我一个旧版本汉克雷斯特。

此错误存在于 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)));
于 2011-02-13T03:19:02.793 回答
9

Java 6 中有一个与此相关的错误

此代码将引发各种错误,例如“找不到符号...”

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);
于 2013-12-23T21:30:58.330 回答
3
assertThat(achievements, hasItem(
    IsInstanceOf.<Achievement>instanceOf(TestAchievement.class)));
于 2011-02-13T02:53:01.653 回答
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)));

它确实有所作为。现在我的测试完美无缺。复制到数组的一行似乎是一种合理的权衡,可以节省很多麻烦。

于 2012-12-14T06:11:48.780 回答
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)));
于 2011-02-13T02:40:16.297 回答
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);
于 2011-02-13T02:46:21.480 回答
2

实际上,即使使用最新版本,它也不适用于更复杂的 Matcher。

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

它不起作用,你会得到:

Assert 类型中的方法 assertThat(T, Matcher) 不适用于参数 (Set, Matcher>)

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

assertThat(result.getAnswers().toArray(), hasItemInArray(Matchers.hasProperty("content", equalTo("<h4>new comment</h4>"))));
于 2013-04-15T00:11:25.987 回答