AssertEquals when list contents are unordered

How would you reorganize the following if products can be returned in any order?

List<Product> products = get_products("test_produc"); assertEquals(products.size(),3); assertEquals(products.get(0).getName(), "test_product1"); assertEquals(products.get(1).getName(), "test_product2"); assertEquals(products.get(2).getName(), "test_produc3"); 

If this can be done gracefully using threads, then I am ready for such suggestions. Hamcrest offers are also welcome.

+7
java junit hamcrest
source share
7 answers

Note that assertEquals also works directly with lists and sets. This takes a lot less typing and it will give very clear error messages.

If return values ​​are not allowed to contain duplicates, they should return a set instead of a list. If you can change the function you are testing, you can test it as follows:

 assertEquals(new HashSet<>(Arrays.asList("Item1", "Item2")), get_products()); 

If this is not an option, you should sort both expected and actual results and compare them:

 asssertEquals(Arrays.sort(Arrays.asList("Item1", "Item2")), Arrays.sort(get_products())); 

Finally, you can resort to using Hamcrest sockets (the containsInAnyOrder function is in org.hamcrest.collection.IsIterableContainingInAnyOrder ):

 assertThat(get_products(), containsInAnyOrder("Item1", "Item2")); 
+7
source share

I would recommend using AssertJ -

 import static org.assertj.core.api.Assertions.assertThat; // ...... List<String> products = get_products("test_produc").stream() .map(Product::getName) .collect(toList()); assertThat(products).containsExactlyInAnyOrder("Third", "Second", "First"); 

which additionally gives you many more free statements (especially exception handling ).

+6
source share

I would match Abubakkar's answer with Hamcrest compare collections

 List<String> productNames = products.stream() .map(p -> p.getName()) .collect(Collectors.toList()); // assert that the actual list does not contain additional elements: assertEquals(products.size(),3); assertThat(productNames, containsInAnyOrder("test_product1", "test_product2", "test_produc3")); 
+3
source share

You can state in a logical state using Stream#anyMatch(Predicate filter) :

Returns whether any elements of this stream match the provided predicate. It is not possible to evaluate a predicate for all elements unless it is necessary to determine the result. If the stream is empty, false returned and the predicate is not evaluated.

 assertEquals(products.size(), 3); assertTrue(products.stream().anyMatch(p -> "test_product1".equals(p.getName()))); assertTrue(products.stream().anyMatch(p -> "test_product2".equals(p.getName()))); assertTrue(products.stream().anyMatch(p -> "test_product3".equals(p.getName()))); 
+2
source share

You can try something like this with stream (I assume you are only interested in getName , and I did not use hamcrest, so just using assertTrue ):

 List<String> productNames = products.stream() .map(p -> p.getName()) .collect(Collectors.toList()); assertTrue(productNames.contains("test_product1")); assertTrue(productNames.contains("test_product2")); assertTrue(productNames.contains("test_product3")); 
+1
source share

In such situations, I prefer to use assertJ. Perhaps this will be satisfactory. Example:

  final List<String> actual = Arrays.asList("c", "b", "a"); final List<String> expected = Arrays.asList("a", "b", "c"); Assertions.assertThat(actual).containsOnlyElementsOf(expected); 
+1
source share

Without knowing the Hamcrest, my decision would be to sort each list (or their copies, if it is unacceptable to change them), and then claim that they are equal.

Strength: Also works if there are duplicate products in the list (the other list will have the same duplicate).

You can use the stream to extract names from the list of products; some of the other answers already show how.

+1
source share

All Articles