3

I am trying to assert for equality the following collections:

String[] arr1= new String[] { "1", "2", "3" };
Collection<String[]> coll1= Arrays.asList(arr1, arr1);

String[] arr2 = new String[] { "1", "2", "3" };
Collection<String[]> coll2 = Arrays.asList(arr2, arr2);

assertEquals(coll1, coll2);

however, I got a result opposite to the expected - an assertion error. The problem is that the arrays are checked for equality with Object.equals() method which actually checks the reference of the arrays which are clearly different.

Is there any handy method I can use from JUnit or Guava to overcome this problem?

EDIT: Notice that I want to compare the Collection objects, not the arrays itself.

jilt3d
  • 3,864
  • 8
  • 34
  • 41

2 Answers2

4

This is where Hamcrest comes to the rescque. Here is the javadoc link. I would suggest using IsArrayContainingInOrder

So...

assertThat(coll1, IsArrayContainingInOrder.arrayContaining(coll2));

sorry, the above would work for the arrays but the below will work for the collections...

assertThat(coll1, IsIterableContainingInOrder.contains(coll2.toArray()));

This uses IsIterableContainingInOrder

FYI, I have found using Hamcrest matchers so elegant that I rarely if ever use non-Hamcrest testing. So all my tests read like

assertThat(myValue, is(true));
assertThat(myValue, equalTo("something"));
assertThat(myList, IsIterableContainingInAnyOrder.containsInAnyOrder(first, second, third));

Off soap box.

John B
  • 32,493
  • 6
  • 77
  • 98
  • This looks interesting, but it seems these definitions are not included in the hamcrest dependency of JUnit 4.10. – jilt3d May 30 '13 at 11:21
  • 2
    True. They come in `hamcrest-all`. see http://mvnrepository.com/artifact/org.hamcrest/hamcrest-all/1.3. If you are using 4.10 of JUnit this can cause some conflicts with Hamcrest (because it includes SOME Hamcrest classes). I recommend updating to JUnit 4.11 which does not have this issue. – John B May 30 '13 at 11:28
  • Here is a discussion of Hamcrest with JUnit. Again remember that JUnit 4.11 has resolved this issue. https://code.google.com/p/hamcrest/issues/detail?id=166 – John B May 30 '13 at 11:31
  • That's it. Even though I should call toArray() of the second collection, I like the solution. It is readable and concise. I have also very nice output when the assertion fails. – jilt3d May 30 '13 at 12:35
  • Yeah, the output on failure is one of the reasons I really prefer Hamcrest. I know the `toArray` thing is a bit annoying but still works very well. Cheers. – John B May 30 '13 at 12:38
  • it seems that the call toArray() is not only annoying but it could be problematic since the collections can be null. Any ideas? – jilt3d May 30 '13 at 13:44
  • General rule would be to NEVER use / allow `null` for a collection but instead use empty collections. I follow this rule. Also, since the argument being passed to the `Matcher` is your `expected` value, it should never be null. If you are expecting null use `CoreMatchers.nullValue()` – John B May 30 '13 at 14:05
  • Yes, I agree - the billion dollar mistake... thanks, I think I am going to change the contract. – jilt3d May 30 '13 at 14:30
3

You could use Arrays#deepEquals:

boolean isSameArrayContent = Arrays.deepEquals(coll1.toArray(), coll2.toArray());
assertTrue(isSameContent);
assylias
  • 321,522
  • 82
  • 660
  • 783
  • The OP doesn't asked for comparing arrays. –  May 30 '13 at 11:44
  • If you call arrays by collections, I have nothing to say to you. –  May 30 '13 at 11:53
  • Firstly you say one then second, I don't understand you point, after that downvoting my answer. Converting is another thing it could be buggy and needs testing separately. –  May 30 '13 at 12:00
  • 3
    +1: I prefer the solution of John B since it is more readable in my opinion. However, your solution doesn't introduce an additional dependency which is a plus. – jilt3d May 30 '13 at 12:39