Question

I am obviously confused about how to use Hamcrest's IsIterableContainingInOrder to verify List equality beyond just using .equals(). I'd like to see Hamcrest's helpful messages in my reports.

Why are the tests below failing to even compile? Some of them are more counter-intuitive than others, at least for me. I get, I think, the general principle that the type parameter will be inferred to what I pass to a method with a varargs signature so it will consider arrays of T as varargs of T and so will generate a Matcher based on T and not on array of T, iterable of T, or anything like that.

I could use an explanation, please, as to why some of the lines that are most intuitive actually fail to even compile.

Particularly:

  • 3 and 4 show the asymmetry of array/List
  • 5 and 6 show that I can look in a List and not in an array (?)

The compiler warning on the line marked as such is even more mysterious to me.


@org.junit.Test
public void testTest() {
  String string1 = "A";
  String string2 = "B";
  String string3 = "C";

  List<String> list1 = Lists.newArrayList(string1, string2, string3);
  List<String> list2 = Lists.newArrayList(string1, string2, "C");

  String[] array1 = list1.toArray(new String[list1.size()]);
  String[] array2 = list2.toArray(new String[list2.size()]);

  // -------------------------------------------------------------------------
  // 1) The assertion after this comment line DOES NOT COMPILE
  // Assert.assertThat(array2, IsIterableContainingInOrder.contains(array1));
  // -------------------------------------------------------------------------
  // 2) The assertion after this comment line DOES NOT COMPILE
  // Assert.assertThat(list2, IsIterableContainingInOrder.contains(list1));
  // -------------------------------------------------------------------------
  // 3) The assertion after this comment line SUCCEEDS
  Assert.assertThat(list2, IsIterableContainingInOrder.contains(array1));
  // -------------------------------------------------------------------------
  // 4) The assertion after this comment line DOES NOT COMPILE + HAS WARNING
  // Assert.assertThat(array2, IsIterableContainingInOrder.contains(list1));
  // -------------------------------------------------------------------------
  // 5) The assertion after this comment line DOES NOT COMPILE
  // Assert.assertThat(array2, IsIterableContainingInOrder.contains(string1));
  // -------------------------------------------------------------------------
  // 6) The assertion after this comment line COMPILES but fails
  Assert.assertThat(list2, IsIterableContainingInOrder.contains(string1));
  // -------------------------------------------------------------------------
  // 7) The assertion after this comment line COMPILES and succeeds
  Assert.assertThat(list2,
      IsIterableContainingInOrder.contains(string1, string2, string3));
  // -------------------------------------------------------------------------
}

Copious amounts of astonishment. :(


PS I realise all of the astonishment comes from my own ignorance and nothing else. I should brush up on Generics, type inference, varargs, etc. I could really use a thorough explanation on this, and I would probably refer back to it a few times going forward.

PPS I did try to read the code first but look at it for a sec... ;) Not for the feint of heart:

@SuppressWarnings("unchecked")
@Factory
public static <E> Matcher<Iterable<? extends E>> contains(final Matcher<? super E> itemMatcher) {
    return contains(new ArrayList<Matcher<? super E>>(asList(itemMatcher)));
}
Was it helpful?

Solution

Here are the aswers... hopefully correct ones :)

// 1) The assertion after this comment line DOES NOT COMPILE
// Assert.assertThat(array2, IsIterableContainingInOrder.contains(array1));

This one does doesn't compile, because arrays don't implement Iteratable.

// 2) The assertion after this comment line DOES NOT COMPILE
// Assert.assertThat(list2, IsIterableContainingInOrder.contains(list1));

For this to work, list2 should be a List<List<String>>, as contains only verifies that the iteratable contains the item that is passed

// 3) The assertion after this comment line SUCCEEDS
Assert.assertThat(list2, IsIterableContainingInOrder.contains(array1));

Passes because array1 is taken as a vararg.

// 4) & 5) 

Same as 1

// 6) The assertion after this comment line COMPILES but fails
Assert.assertThat(list2, IsIterableContainingInOrder.contains(string1));

Contains expects all the items in the collection, not just a subset.

// 7)

Similar as 3, but with each item passed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top