JUnit 4 сравнить наборы

103

Как бы вы лаконично заявили о равенстве Collectionэлементов, в частности a Setв JUnit 4?

Eqbal
источник
2
проверьте это сообщение SO stackoverflow.com/questions/1086691/collectionassert-in-junit
Teja Kantamneni
Вы пытаетесь утверждать, что два набора равны друг другу (содержат одинаковые элементы) или что два элемента одного набора равны?
Bill the Lizard,
Мне нужно увидеть, что элементы двух Наборов равны
Eqbal

Ответы:

104

Вы можете утверждать, что два Sets равны друг другу, что вызывает Set equals()метод .

public class SimpleTest {

    private Set<String> setA;
    private Set<String> setB;

    @Before
    public void setUp() {
        setA = new HashSet<String>();
        setA.add("Testing...");
        setB = new HashSet<String>();
        setB.add("Testing...");
    }

    @Test
    public void testEqualSets() {
        assertEquals( setA, setB );
    }
}

Это @Testпройдет, если два Setэлемента имеют одинаковый размер и содержат одинаковые элементы.

Билл Ящерица
источник
7
Это не показывает очень хорошие результаты в отчете. Если ваши toStrings четко определены, это лучше, но все же не очень хорошо (небольшая разница может закончиться страницей текста)
Bill K
Ухм, как же я получаю: java.lang.AssertionError: ожидалось: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteIdtable./ <434279tils>, но был = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Джованни Ботта
3
@Giodude У вас есть equalsи hashCodeреализован ли класс, который вы храните в своей Hashtable?
Bill the Lizard
Как видите, это просто строки и длинный ... Я тестирую Avro для сериализации и десериализации карты, и вот результат. Я думаю, что должно быть что-то подозрительное в том, как строки сериализуются и десериализуются, что приводит к сбою теста, но я не могу найти проблему.
Джованни Ботта
У меня не сработало, хотя я сравниваю два HashSet <Long>. Ответ @MattFriedman действительно работает для моего варианта использования.
bluecollarcoder
46

Apache снова приходит на помощь.

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));

Работает как шарм. Не знаю почему, но я обнаружил, что с коллекциями assertEquals(coll1, coll2)не всегда работает следующее. В случае, если это не удалось для меня, у меня было две коллекции, поддерживаемые Sets. Ни хамкрест, ни юнит не сказали бы, что коллекции были равны, хотя я точно знал, что они равны. Используя CollectionUtils, он отлично работает.

Мэтт Фридман
источник
20
На самом деле это тривиально, сложная часть состоит в том, чтобы четко указать вызывающему абоненту разницу
Билл К.
1
Принятый ответ является хорошим ответом на исходный вопрос (модульный тест специально для двух наборов), но этот ответ с помощью CollectionUtils, я думаю, является лучшим ответом для наиболее общего случая. Я не смог сравнить коллекцию и набор, если не использовал CollectionUtils.
Джей
16

с окорочком :

assertThat(s1, is(s2));

с простым утверждением:

assertEquals(s1, s2);

Примечание: Метод т равенства () из множества бетона класса используется

DFA
источник
1
Я предпочитаю этот метод, так как Hamcrest поставляется с JUnit 4, поэтому другие библиотеки не нужны.
JRSofty
2
Это может не сработать, если наборы имеют разные типы.
Hans-Peter Störr
7

Особенно интересен случай, когда вы сравниваете

   java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

и

   java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>

Пока что единственное решение, которое я вижу, - это заменить их оба наборами

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));

Или я мог бы сравнить их элемент за элементом.


источник
На самом деле для этого есть несколько решений, представленных в других ответах. В любом случае наборы для этого немного неудачны, поскольку они игнорируют порядок. Возможно, ArrayList?
Hans-Peter Störr
4

В качестве дополнительного метода, основанного на массиве ... вы можете рассмотреть возможность использования утверждений неупорядоченного массива в junitx. Хотя пример Apache CollectionUtils будет работать, там также есть набор надежных расширений утверждений:

Я думаю, что

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});

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

Конечно, недостатком здесь является то, что junitx - это дополнительный файл jar или запись maven ...

 <dependency org="junit-addons" name="junit-addons" rev="1.4"/>
jayunit100
источник
2

Проверьте эту статью . Один пример оттуда:

@Test  
public void listEquality() {  
    List<Integer> expected = new ArrayList<Integer>();  
    expected.add(5);  

    List<Integer> actual = new ArrayList<Integer>();  
    actual.add(5);  

    assertEquals(expected, actual);  
}  
Римский
источник
короткая, но отличная ссылка, очень быстро объясняет, что вы можете сделать с Junit4-
Йоханнес
1
Ссылка не работает. Есть ли шанс найти в Интернете архивную версию или обобщить ее содержание?
pzp
1

Использование Hamcrest:

assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));

Это также работает, когда наборы имеют разные типы данных, и сообщает о различиях, а не просто об ошибках.

Ханс-Петер Штёрр
источник
2
Что такое импорт для isIn? IntelliJ не может разрешить импорт с каким-либо пакетом hamcret.
fabien
0

Если вы хотите проверить, содержит ли List или Set набор определенных значений (вместо сравнения его с уже существующей коллекцией), часто бывает удобен метод toString коллекций:

String[] actualResult = calltestedmethod();
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());

List otherResult = callothertestedmethod();
assertEquals("[42, mice]", otherResult.toString());

Это немного короче, чем первое построение ожидаемой коллекции и сравнение ее с фактической коллекцией, и ее проще написать и исправить.

(Следует признать, что это не особо чистый метод, и он не может отличить элемент «foo, bar» от двух элементов «foo» и «bar». Но на практике я думаю, что наиболее важным является то, что писать тесты легко и быстро. , иначе многие разработчики просто не будут без давления.)

Ханс-Петер Штёрр
источник
Это делает результат вашего модульного теста зависимым от реализации toString from list. Если они решат изменить форматирование, юнит-тест больше не будет работать. Я бы не считал это безопасным.
Laurens Op 't Zandt,
@ LaurensOp'tZandt Вы имеете в виду, что Oracle меняет формат Collection.toList ()? Этого точно не произойдет. Вы, однако, правы, это не особо чисто. Но на практике у меня сложилось впечатление, что это самое главное, что тесты писать очень легко.
Hans-Peter Störr
Я согласен, я думаю, что метод toString вряд ли удастся. Так что, вероятно, он продолжит работать. Я просто хотел указать, что это не очень чистый способ. Но на самом деле это очень просто. Одна проблема, возникающая при сравнении наборов. Поскольку их порядок не гарантируется.
Laurens Op 't Zandt,
0

Мне нравится решение Ханса-Петера Штёрра ... Но я считаю, что оно не совсем правильное. К сожалению containsInAnyOrder, не приемлет ни Collectionодного объекта для сравнения. Так что это должно быть Collectionиз Matchers:

assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))

Импорт:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
FLUXчастица
источник