Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Проверки

Проверка (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.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.