JUnit 4 порівняти Набори


102

Як би ви лаконічно стверджували рівність Collectionелементів, зокрема Setу JUnit 4?



Ви намагаєтесь стверджувати, що два набори рівні між собою (містять однакові елементи) або два елементи одного набору рівні?
Білл Ящірка

Мені потрібно побачити, що елементи двох наборів рівні
Екбал

Відповіді:


103

Ви можете стверджувати, що два 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пройде, якщо два Sets однакового розміру і містять однакові елементи.


7
Це не дає дуже хороших результатів у звіті. Якщо ваші параметри чітко визначені, це краще, але все-таки не добре (Невелика різниця може закінчитися сторінкою тексту)
Білл К

Uhm, як це я отримую: java.lang.AssertionError: очікувано: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Категорія = AvrIfd, QuoteI20 = 27427_926_0262 = 41427_0262 = 41427 = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, категорія = AvrIfd, QuoteId = 4342740204922826921}>
Джованні Ботта

3
@Giodude У вас є equalsі hashCodeреалізований у класі, який ви зберігаєте у своєму Hashtable?
Білл Ящірка

Як ви бачите, це просто рядки і довгі ... Я тестую Avro на серіалізацію та десеріалізацію карти, і ось результат. Я думаю, що має бути щось рибне з тим, як рядки серіалізуються та десеріалізуються, що робить тест невдалим, але я не можу знайти проблему.
Джованні Ботта

Не працювало для мене, хоча я порівнював два HashSet <Long>. Відповідь @MattFriedman насправді працює для мого випадку використання.
bluecollarcoder

46

Апач знову приходить на допомогу.

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
Це може не спрацювати, коли набори мають різні типи.
Ганс-Пітер Стрер

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?
Ганс-Пітер Стрер

4

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

Я думаю, що

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

підхід буде для вас набагато більш читабельним та налагоджуваним (всі колекції підтримують arraray (), тому використовувати методи 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 не може вирішити імпорт жодним пакунковим пакетом.
fabien

0

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

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

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

Це трохи коротше, ніж спочатку створити очікувану колекцію та порівняти її з фактичною колекцією, і простіше писати та виправляти.

(Правда, це не особливо чистий метод, і він не може відрізнити елемент "foo, bar" від двох елементів "foo" і "bar". Але на практиці я думаю, що найголовніше, щоб писати тести було легко і швидко. , інакше багато розробників просто не обійдуться без натискання.)


Це робить результат вашого тесту на одиницю залежним від реалізації ToString зі списку. Якщо вони вирішать змінити форматування, тестовий пристрій більше не працюватиме. Я б не вважав це безпечним.
Laurens Op 't Zandt

@ LaurensOp'tZandt Ви маєте на увазі, що Oracle змінює формат Collection.toList ()? Це точно не відбудеться. Ти правда маєш рацію, яка не є особливо чистою. Але на практиці моє враження, що найголовніше, щоб писати тести дуже легко.
Ганс-Пітер Штерр

Я згоден, я думаю, що метод toString, ймовірно, не має шансів. Тож, ймовірно, це буде продовжувати працювати. Я просто хотів зазначити, що це не дуже чистий спосіб. Але насправді це дуже просто. Одна з проблем, яка виникає при порівнянні множин. Оскільки їх порядок не гарантується.
Laurens Op 't Zandt

0

Мені подобається рішення Ганса-Пітера Стрьора ... Але я думаю, що це не зовсім коректно. На жаль containsInAnyOrder, не приймає Collectionоб'єктів для порівняння. Тому він повинен бути Collectionз Matcherз:

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.