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


103

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


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

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


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"/>

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;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.