assertTrue () / assertFalse (): використовувати лише для затвердження булевого результату, що повертається
assertTrue (Iterables.elementsEqual (argumentComponents, returnComponents));
Ви хочете використовувати Assert.assertTrue()або Assert.assertFalse()як тестований метод повертає booleanзначення.
Оскільки метод повертає конкретну річ, таку як Listяка повинна містити деякі очікувані елементи, твердження assertTrue()таким чином: Assert.assertTrue(myActualList.containsAll(myExpectedList)
є анти шаблоном.
Це полегшує написання твердження, але оскільки тест не вдається, це також ускладнює налагодження, оскільки тест-драйвер скаже вам лише щось на зразок:
очікуваний, trueале фактичний єfalse
Assert.assertEquals(Object, Object)в JUnit4 або Assertions.assertIterableEquals(Iterable, Iterable)в JUnit 5: використовувати лише як обидва, equals()і toString()перевизначені для класів (і глибоко) порівняних об'єктів
Це має значення, оскільки тест на рівність у твердженні покладається, equals()а повідомлення про помилку тесту toString()- на порівнювані об’єкти.
Оскільки Stringзамінює обидва equals()і toString(), цілком справедливо стверджувати List<String>с assertEquals(Object,Object). А щодо цього: вам доведеться перевизначити equals()в класі, оскільки це має сенс з точки зору рівності об’єктів, а не лише для полегшення тверджень у тесті з JUnit.
Для полегшення тверджень у вас є інші способи (це ви можете побачити в наступних пунктах відповіді).
Чи є Гуава способом виконати / побудувати твердження щодо модульних тестів?
Чи є Google Guava Iterables.elementsEqual () найкращим способом порівняти ці два списки за умови, що у мене є бібліотека на шляху до збірки?
Ні, це не так. Гуава - це не бібліотека для написання тверджень модульного тесту.
Вам це не потрібно для написання більшості (все, що я думаю) з модульних тестів.
Який канонічний спосіб порівняння списків для модульних тестів?
Як хорошу практику я віддаю перевагу бібліотекам тверджень / збігів.
Я не можу заохотити JUnit виконувати конкретні твердження, оскільки це забезпечує насправді занадто мало і обмежених можливостей: він виконує лише твердження з глибокими рівними.
Іноді ви хочете дозволити будь-який порядок в елементах, іноді ви хочете дозволити, щоб будь-які елементи очікуваного збігалися з фактичними, і так для ...
Отже, правильним способом є використання бібліотеки тверджень / збігів для модульного тестування, таких як Hamcrest або AssertJ.
Фактична відповідь забезпечує рішення Гамкреста. Ось рішення AssertJ .
org.assertj.core.api.ListAssert.containsExactly() це те, що вам потрібно: він перевіряє, що фактична група містить точно задані значення і нічого іншого, в порядку, як зазначено:
Перевіряє, що фактична група містить точно вказані значення і нічого іншого, по порядку.
Ваш тест може виглядати так:
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
@Test
void ofComponent_AssertJ() throws Exception {
MyObject myObject = MyObject.ofComponents("One", "Two", "Three");
Assertions.assertThat(myObject.getComponents())
.containsExactly("One", "Two", "Three");
}
Хорошим моментом у AssertJ є те, що оголошувати Listочікуване без потреби: це робить твердження випрямленішим, а код більш читабельним:
Assertions.assertThat(myObject.getComponents())
.containsExactly("One", "Two", "Three");
І якщо тест не вдається:
Assertions.assertThat(myObject.getComponents())
.containsExactly("One", "Two");
ви отримуєте дуже чітке повідомлення, таке як:
java.lang.AssertionError:
Очікуючи:
<["Один", "Два", "Три"]>
містити точно (і в тому самому порядку):
<["Один", "Два"]>
але деякі елементи не очікувались:
<["Три"]>
Бібліотеки тверджень / збігів є обов’язковими, оскільки вони дійсно будуть надалі
Припустимо , що MyObjectне зберігає Strings , але FooS примірників таких як:
public class MyFooObject {
private List<Foo> values;
@SafeVarargs
public static MyFooObject ofComponents(Foo... values) {
}
public List<Foo> getComponents(){
return new ArrayList<>(values);
}
}
Це дуже поширена потреба. З AssertJ твердження все ще просто написати. Краще ви можете стверджувати, що вміст списку рівний, навіть якщо клас елементів не замінює, equals()/hashCode()тоді як способи JUnit вимагають, щоб:
import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;
@Test
void ofComponent() throws Exception {
MyFooObject myObject = MyFooObject.ofComponents(new Foo(1, "One"), new Foo(2, "Two"), new Foo(3, "Three"));
Assertions.assertThat(myObject.getComponents())
.extracting(Foo::getId, Foo::getName)
.containsExactly(tuple(1, "One"),
tuple(2, "Two"),
tuple(3, "Three"));
}