Java Hamcrest : Collection contains item of type
Solution 1
Thanks for all the help.
The posts here suggested it was a defect with Hamcrest, so I headed over to the hacmrest site to register a bug, whien I discovered that the mvn / ivy dependency declaration I was using was out-of-date, giving me an old version of Hamcrest.
This bug exists with 1.1, which is the latest if declared using
<dependency org="org.hamcrest" name="hamcrest-all" rev="1.1">
However, the correct depedency declaration is:
<dependency org="org.hamcrest" name="hamcrest-library" rev="1.3.RC2"/>
Updating to this solved the issue. The syntax used in my test is:
assertThat(achievements, hasItem(isA(TestAchievement.class)));
Solution 2
There is a bug in Java 6 that relates to this.
This code will throw various errors such as "cannot find symbol..."
assertThat(achievements, hasItem(isA(TestAchievement.class)));
The work around for this is to declare the matcher as a variable and then reference that variable. It is important to note that the type of the variable, specifically the generics section, is very important for this to work.
Matcher<Iterable<? super TestAchievement>> matcher = hasItem(isA(TestAchievement.class));
assertThat(achievements, matcher);
Interestingly if you use instanceOf()
instead of isA()
you once again run into issue. (although if you ignore the warnings this might just work for you anyway.) Expanding on the previous fix you can use:
Matcher<TestAchievement> itemMatcher = Matchers.instanceOf(TestAchievement.class);
Matcher<Iterable<? super TestAchievement>> matcher = hasItem(itemMatcher);
assertThat(achievements, matcher);
Solution 3
assertThat(achievements, hasItem(
IsInstanceOf.<Achievement>instanceOf(TestAchievement.class)));
Solution 4
I've been battling with this for a while, none of the approaches here really had the expected result. Out of pure despair I tried converting to an array to see if that made a difference:
List<Object> listOfThings = (List) someService.findThings(); // your business logic here
Object[] arrayOfThings = listOfThings.toArray(new Object[listOfThings.size()]);
assertThat(arrayOfThings, hasItemInArray(instanceOf(SpecialThing.class)));
And it did make a difference. Now my test works flawlessly. The one line of copy-to-array seems to be a reasonable trade-off to save a lot of hassle.
Solution 5
I have been futzing around with this for awhile, and it seems like the only way I know is to convert List<Achievement>
to List<Object>
. The problem is CoreMatchers.instanceOf()
returns Matcher<Object>
.
With that modification, I'm able to get this to work:-
List<Object> achievements = new ArrayList<Object>();
achievements.add(new Achievement());
achievements.add(new TestAchievement());
assertThat(achievements, hasItem(instanceOf(TestAchievement.class)));
Marty Pitt
Updated on June 06, 2022Comments
-
Marty Pitt almost 2 years
I'd like to assert that
List<Achievement>
contains a member of typeTestAchievement
.Here's my assertion:
List<Achievement> achievements; // Populated elsewhere assertThat(achievements,hasItem(isA(TestAchievement.class)));
This doesn't compile, reporting the error:
The method assertThat(T, Matcher) in the type Assert is not applicable for the arguments (List, Matcher<Iterable<TestAchievement>>)
What's the correct syntax for this type of assertion using Hamcrest?
-
limc about 13 yearsThat line doesn't compile. Here's the error message:
The method instanceOf(Class<?>) of type IsInstanceOf is not generic; it cannot be parameterized with arguments <Achievement>
-
tchrist about 13 yearsI spent nearly a week of headbanging once on this very same problem of a buggy declaration in the hamcrest library code before I finally stumbled on the fixed updated version. Just nuts! Things should not be this complicated.
-
NamshubWriter about 13 years@limc It's generic in the code at the trunk: code.google.com/p/hamcrest/source/browse/trunk/hamcrest-java/…
-
Jesper Rønn-Jensen about 13 yearsThis is a good example. Works for me but only on hamcrest 1.1. Upgrading to 1.2 or 1.3.0RC0 will give me n error.
-
Jesper Rønn-Jensen about 13 yearsThe error (for 1.2) stacktrace: java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:31) at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:14) at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:54) at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:12) at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8)
-
Mike Rylander over 10 yearsI typically add the comment
// work around for Java 6 Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7034548
whenever this comes up. -
Mike Rylander over 10 yearsIf you want to avoid using primitive arrays see this answer. (You will still have the one extra line though.)
-
Mike Rylander over 10 years@JesperRønn-Jensen See this answer. This works with hamcrest 1.1 and 1.3.