Проверки
Проверка (assertion) — метод, который проверяет условие и останавливает тест с ошибкой, если условие ложно. Все проверки JUnit — статические методы класса org.junit.jupiter.api.Assertions. Кроме assertEquals их ещё с десяток; в этом уроке — те, что нужны каждый день.
Пост блога
Дальше часть примеров тестирует блог. Пост — запись в src/main/java/com/example/blog/Post.java:
// src/main/java/com/example/blog/Post.java
package com.example.blog;
public record Post(Long id, String title, String author, boolean published) {
public Post publish() {
return new Post(id, title, author, true);
}
}У нового поста ещё нет id, и он черновик. publish() не меняет запись, а возвращает опубликованную копию.
Основные проверки
| Проверка | Проходит, когда |
|---|---|
assertEquals(expected, actual) | Значения равны по equals() |
assertNotEquals(a, b) | Значения различаются |
assertTrue(condition) / assertFalse(condition) | Условие true / false |
assertNull(value) / assertNotNull(value) | Значение null / не null |
assertSame(a, b) | Это один и тот же объект, a == b |
assertIterableEquals(expected, actual) | В двух коллекциях равные элементы в том же порядке |
fail("сообщение") | Никогда: тест падает безусловно |
// src/test/java/com/example/blog/PostTest.java
package com.example.blog;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PostTest {
@Test
void newPostIsDraft() {
Post post = new Post(null, "Привет, JUnit", "anna", false);
assertNull(post.id());
assertFalse(post.published());
}
@Test
void publishReturnsPublishedCopy() {
Post draft = new Post(1L, "Привет, JUnit", "anna", false);
Post published = draft.publish();
assertNotNull(published);
assertTrue(published.published(), "publish() должен поставить флаг");
assertFalse(draft.published(), "исходный пост не должен меняться");
}
}Импорт со * подключает сразу все проверки. Оба теста проходят.
Сообщение при падении
Последний параметр любой проверки — сообщение. Без него assertTrue говорит только expected: <true> but was: <false>, с ним причина ясна:
org.opentest4j.AssertionFailedError: publish() должен поставить флаг ==> expected: <true> but was: <false>Если собирать сообщение дорого, передайте лямбду: () -> "пост " + post — она вызовется, только когда проверка не пройдёт.
Несколько проверок сразу: assertAll
Обычно тест останавливается на первой упавшей проверке, и про остальные вы не узнаете. assertAll выполняет все проверки и сообщает обо всех падениях вместе:
// src/test/java/com/example/blog/PostTest.java
@Test
void publishKeepsOtherFields() {
Post published = new Post(1L, "Привет, JUnit", "anna", false).publish();
assertAll(
() -> assertEquals(1L, published.id()),
() -> assertEquals("Привет, JUnit", published.title()),
() -> assertEquals("anna", published.author()),
() -> assertTrue(published.published())
);
}Если бы тест ждал заголовок "Привет" и автора "oleg", отчёт перечислил бы оба падения:
org.opentest4j.MultipleFailuresError:
Multiple Failures (2 failures)
org.opentest4j.AssertionFailedError: expected: <Привет> but was: <Привет, JUnit>
org.opentest4j.AssertionFailedError: expected: <oleg> but was: <anna>Коллекции
assertIterableEquals сравнивает поэлементно и говорит, где различие:
// src/test/java/com/example/blog/PostTest.java
assertIterableEquals(List.of("Первый", "Второй"), List.of("Первый", "Третий"));org.opentest4j.AssertionFailedError: iterable contents differ at index [1], expected: <Второй> but was: <Третий>Частая ошибка
BigDecimal.equals() сравнивает не только значение, но и масштаб — число знаков после точки. 36 и 36.00 для него разные:
// src/test/java/com/example/shop/PriceCalculatorTest.java
assertEquals(new BigDecimal("36"), calculator.total(new BigDecimal("12"), 3));org.opentest4j.AssertionFailedError: expected: <36> but was: <36.00>Пишите ожидаемую сумму с тем же масштабом, что возвращает код ("36.00"), или сравнивайте через compareTo: assertEquals(0, expected.compareTo(actual)). В AssertJ для этого есть готовый isEqualByComparingTo.