AssertEquals, когда содержимое списка неупорядочено [дубликат]


На этот вопрос уже есть ответ здесь:

Как бы вы рефакторировали следующее, если продукты могут быть возвращены в любом порядке?

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

Если это можно сделать элегантно, используя потоки, то я готов к таким предложениям. Предложения Hamcrest также приветствуются.

7 7

7 ответов:

Обратите внимание, что assertEquals также работает непосредственно со списками и наборами. Это намного меньше ввода текста, и это даст очень четкие сообщения об ошибках.

Если возвращаемые значения не могут содержать дубликатов, они должны возвращать набор вместо списка. Если вы можете изменить функцию, которую вы тестируете, таким образом, вы можете проверить ее следующим образом:

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

Если это не вариант, вы должны отсортировать как ожидаемые, так и фактические результаты и сравнить их:

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

Наконец-то вы можете прибегнуть к используя Hamcrest вычислителей (функция containsInAnyOrder в org.hamcrest.collection.IsIterableContainingInAnyOrder):

assertThat(get_products(), containsInAnyOrder("Item1", "Item2"));

Я бы рекомендовал использовать 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");

, что дополнительно дает вам много более плавных утверждений (особенно , обрабатывающих исключения).

Я бы объединил ответ Абубакара с 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"));

Вы можете утверждать о булевом условии, используя Stream#anyMatch(Predicate filter):

Возвращает, соответствуют ли какие-либо элементы этого потока предоставленному предикату. Не может оценивать предикат по всем элементам, если это не необходимо для определения результата. Если поток пуст, то возвращается false и предикат не вычисляется.

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

В таких ситуациях я предпочитаю использовать assertJ. Может быть, это будет приятно. Пример:

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

Вы можете попробовать что-то вроде этого, используя stream (я предполагаю, что вас интересует только getName, и я не использовал hamcrest, поэтому использую просто 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"));

Не зная Хэмкреста, я решил бы отсортировать каждый список (или их копии, если их нельзя изменить), а затем утверждать, что они равны.

Strength: также работает, если в списке есть дубликаты продуктов (потребуется такой же дубликат в другом списке).

Вы можете использовать поток для извлечения имен из списка продуктов; некоторые другие ответы уже показывают, как это сделать.