3

Why does this test fail? I know contains works when you pass in individual strings separated by commas but I wanted to see if it's possible to just pass in an entire list of strings instead. I just want to make sure that list 1 contains all of the contents of list 2.

@Test
public void testContains() {
    String expected1 = "hello";
    String expected2 = "goodbye";
    List<String> expectedStrings = new ArrayList<>();
    expectedStrings.add(expected1);
    expectedStrings.add(expected2);
    List<String> actualStrings = new ArrayList<>();
    actualStrings.add(expected1);
    actualStrings.add(expected2);
    assertThat(actualStrings, contains(expectedStrings));
}

Is it considered acceptable to use this assertion instead?

assertThat(actualStrings, is(expectedStrings));
Charles H
  • 625
  • 1
  • 7
  • 11
  • containsAll instead of contains. check [API](https://docs.oracle.com/javase/8/docs/api/java/util/List.html#containsAll-java.util.Collection-) – Rahul Sharma Mar 14 '16 at 19:02
  • @RahulSharma so you would use it like `assertThat(actualStrings.containsAll(expectedStrings), is(true))`? – Charles H Mar 15 '16 at 12:19
  • @RahulSharma I was looking more for if there is a hamcrest matcher similar to the List method `containsAll` so I can do this instead: `assertThat(actualStrings, containsAll(expectedStrings))`. I think it reads better than the `is(true)` matcher. – Charles H Mar 15 '16 at 12:29
  • I don't really know how to do that with hamcrest. I use JUnit asserts in my tests. JUnit has most of the hamcrest functionality pulled in, if using hamcrest is not mandatory in your case I would suggest using JUnit. – Rahul Sharma Mar 15 '16 at 13:09
  • @RahulSharma Ok so what would your JUnit assert look like in this case? – Charles H Mar 15 '16 at 13:24
  • assertTrue(actualStrings.containsAll(expectedStrings)) – Rahul Sharma Mar 15 '16 at 13:32
  • @RahulSharma Ah ok. I've just been trying to get in the habit of using assertThat instead of assertTrue b/c of the better failure messages. But yes this will work. Thanks. – Charles H Mar 15 '16 at 15:56
  • Sorry just curious what do you mean 'Better failure messages'? – Rahul Sharma Mar 15 '16 at 16:06
  • @RahulSharma Check out this article -> https://objectpartners.com/2013/09/18/the-benefits-of-using-assertthat-over-other-assert-methods-in-unit-tests/ – Charles H Mar 15 '16 at 18:48
  • @RahulSharma Also here -> http://stackoverflow.com/a/1701143/4702682 – Charles H Mar 15 '16 at 18:50
  • The article and the answer are quite old, 2013 and 2012. Things have changed over the years. Every single drawback of assertTrue(or other methods) which is mentioned in the article has been improved and incorporated. AssertTrue now gives the complete failure message with the values of actual and expected. Also the assert methods allow you to add custom message which sometimes are quite helpful – Rahul Sharma Mar 15 '16 at 20:02
  • @RahulSharma That's interesting, I'll have to look into that. Thanks for the info. – Charles H Mar 16 '16 at 14:29

2 Answers2

2

There is no overloaded contains method which takes a list of expected values.

In the statement assertThat(actualStrings, contains(expectedStrings)) the following method (in the Matchers class) is called:

<E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(E... items)

Basically you are saying that you expect a list with one element and this element is expectedStrings but in fact it is expected1 (E is of type List<String> and not String). To verify add the following to the test which should then pass:

List<List<String>> listOfactualStrings = new ArrayList<>();
listOfactualStrings.add(actualStrings);
assertThat(listOfactualStrings, contains(expectedStrings));

To make the assertion work you have to convert the list to an array:

assertThat(actualStrings, contains(expectedStrings.toArray()));
eee
  • 3,241
  • 1
  • 17
  • 34
0

If you want to apply a matcher for each item in a list you can use the everyItem matcher, like so:

everyItem(not(isEmptyOrNullString()))
lanoxx
  • 12,249
  • 13
  • 87
  • 142