views:

1522

answers:

6

Why does this not compile, oh, what to do?

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

error copied from comment:

cannot find symbol method assertThat(java.util.ArrayList<java.lang.Integer>, org.hamcreset.Matcher<java.lang.Iterable<java.util.ArrayList<java.lang.Integer>>>)
+2  A: 

You are comparing ArrayList<Integer> with int. The correct comparison is:

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

-- Edit --

I'm sorry, I've read it wrong. Anyway, the signature of hasItems you want is:

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

i.e., it accepts a variable number of arguments. I'm not sure if an ArrayList<T> is compatible, just guessing here. Try sending each item from the expected list interspersed by comma.

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

-- Edit 2 --

Just pasting here my comment, there is an equivalent expression for what you want, without using Hamcrest:

assertTrue(actual.containsAll(expected));
freitass
I'm comparing multiple items. (hasItems, not hasItem)
ripper234
So, hamcrest simply does not support comparing two collections?(I don't have an actual list of items, I'm building the list of numbers from 0 to 999 I must compare collections).
ripper234
I cannot answer that for you, I'm telling this based on the documentation. But there is a simpler way to do what you want... use assertTrue(actual.containsAll(expected)).
freitass
@freitass - it's simpler, but when this assert fails you get a very cryptic error messages, which is less helpful than the error message that I imagine hasItems outputs.
ripper234
A: 

That error message looks like one produced by the javac compiler. I've found in the past that code written using hamcrest just won't compile under javac. The same code will compile fine under, say, the Eclipse compiler.

I think Hamcrest's generics are exercising corner cases in generics that javac can't deal with.

skaffman
Wow, interesting. So you're saying the above code is legitimate java code?
ripper234
No, I'm saying that javac sometimes rejects legitimate java code, and hamcrest is a common cause of it.
skaffman
A: 

Try

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

to satisfy the matcher signature. No Eclipse around, so this might not work.

Robert Munteanu
A: 

hasItems checks that a collection contains some items, not that 2 collections are equal, just use the normal equality assertions for that. So either assertEquals(a, b) or using 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));
Dan Godfrey
A: 

What if I have an ArrayList of SomeObject and I want o to SomeObject.getValue() to another array of values?

Rob
A: 
ArrayList<Integer> expected = new ArrayList<Integer>();
expected.add(1);
expected.add(2);
hasItems(expected);

hasItems(T..t) is being expanded by the compiler to:

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

You are passing a single element array containing an ArrayList. If you change the ArrayList to an Array, then your code will work.

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

This will be expanded to:

hasItems(1, 2);
Matthew