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
не зберігає String
s , але Foo
S примірників таких як:
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"));
}