JavaRush /Курсы /Модуль 5. Spring /Лекция 132: Unit-тесты с использованием JUnit 5

Лекция 132: Unit-тесты с использованием JUnit 5

Модуль 5. Spring
14 уровень , 1 лекция
Открыта

Сегодня мы изучим основы Unit-тестирования с использованием JUnit 5.

Давайте разберемся, как использовать эту силу для создания качественного и безопасного кода.

Что такое JUnit 5 и зачем он нужен?

JUnit 5 — это современная версия популярного фреймворка для тестирования на Java. Его цель — помочь разработчикам писать качественные Unit-тесты. Преимущество JUnit 5 состоит в его модульности и гибкости. Вот основные компоненты JUnit 5:

  • JUnit Platform: отвечает за запуск тестов.
  • JUnit Jupiter: предоставляет новые функции и аннотации для тестирования.
  • JUnit Vintage: позволяет запускать старые тесты, написанные на JUnit 3 и 4 (археологи, это для вас).

Почему JUnit 5? Потому что:

  • Он поддерживает Java 8 и выше, включая лямбды и методы по умолчанию.
  • Больше возможностей для настройки жизненного цикла тестов.
  • Удобнейшая аннотация @DisplayName, чтобы ваши тесты выглядели красиво и понятно.

Основные аннотации JUnit 5

Аннотации — это как указатели для JUnit, которые сообщают ему, что и как тестировать.

@Test

Самая главная аннотация. Если вы хотите, чтобы код выполнился как тест, просто пометьте метод этой аннотацией.


import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class MathTest {

    @Test
    void additionTest() {
        int result = 2 + 3;
        assertEquals(5, result, "2 + 3 должно быть равно 5");
    }
}

@BeforeEach и @AfterEach

Используются для выполнения действий до и после каждого теста. Например, настройка тестовой среды или очистка ресурсов.


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;

class LifecycleTest {

    @BeforeEach
    void setUp() {
        System.out.println("Подготовка перед тестом");
    }

    @AfterEach
    void tearDown() {
        System.out.println("Очистка после теста");
    }

    @Test
    void simpleTest() {
        System.out.println("Выполнение теста");
    }
}

Выводы будут такие:


Подготовка перед тестом
Выполнение теста
Очистка после теста

@BeforeAll и @AfterAll

Используются для выполнения действий до или после всех тестов в классе. Эти методы должны быть статическими.


import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterAll;

class GlobalSetupTest {

    @BeforeAll
    static void init() {
        System.out.println("Подготовка перед ВСЕМИ тестами");
    }

    @AfterAll
    static void cleanup() {
        System.out.println("Очистка после ВСЕХ тестов");
    }

    @Test
    void testOne() {
        System.out.println("Первый тест");
    }

    @Test
    void testTwo() {
        System.out.println("Второй тест");
    }
}

Вывод:


Подготовка перед ВСЕМИ тестами
Первый тест
Второй тест
Очистка после ВСЕХ тестов

@DisplayName

Добавьте растение в цифровую пустыню ваших тестов! Делайте их красивее с @DisplayName.

@Test
@DisplayName("Проверка сложения: 2 + 2 = 4")
void additionTest() {
    assertEquals(4, 2 + 2);
}

Основные Assertions

Assertions — это как контрольные точки. Они проверяют, правильно ли работает ваш код.

Assertion Описание Пример
assertEquals(expected, actual) Проверяет, равны ли ожидаемое и фактическое assertEquals(4, 2 + 2)
assertNotEquals(unexpected, actual) Проверяет, НЕ равны ли значения assertNotEquals(5, 2 + 2)
assertTrue(condition) Утверждает, что условие истина assertTrue(2 + 2 == 4)
assertFalse(condition) Утверждает, что условие ложно assertFalse(2 + 2 == 5)
assertNull(object) Проверяет, что объект равен null assertNull(nullVariable)
assertNotNull(object) Проверяет, что объект НЕ равен null assertNotNull(nonNullVariable)
assertThrows(exception, lambda) Проверяет, что код вызывает указанное исключение assertThrows(NumberFormatException.class, () -> Integer.parseInt("NaN"))

Пример:

@Test
void testAssertions() {
    assertEquals(4, 2 + 2, "Сложение двух чисел должно быть корректным");
    assertTrue(3 > 2, "3 больше 2 - это правда");
    assertThrows(ArithmeticException.class, () -> {
        int result = 10 / 0;
    }, "Ожидалось ArithmeticException при делении на 0");
}

Жизненный цикл тестов в JUnit 5

Тесты в JUnit проходят через определённый жизненный цикл:

  1. Создаётся объект тестового класса.
  2. Вызывается метод с аннотацией @BeforeEach.
  3. Выполняется тест.
  4. Вызывается метод с аннотацией @AfterEach.
  5. Повторяется для каждого теста.

Методы с аннотациями @BeforeAll и @AfterAll выполняются один раз на весь класс.


Практика: Написание Unit-тестов для простых методов

Допустим, у нас есть класс Calculator:


class Calculator {

    int add(int a, int b) {
        return a + b;
    }

    int subtract(int a, int b) {
        return a - b;
    }

    int multiply(int a, int b) {
        return a * b;
    }

    int divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("Деление на ноль не допускается");
        }
        return a / b;
    }
}

И тесты к нему:


import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    Calculator calculator = new Calculator();

    @Test
    void testAddition() {
        assertEquals(5, calculator.add(2, 3), "2 + 3 должно быть равно 5");
    }

    @Test
    void testSubtraction() {
        assertEquals(1, calculator.subtract(3, 2), "3 - 2 должно быть равно 1");
    }

    @Test
    void testMultiplication() {
        assertEquals(6, calculator.multiply(2, 3), "2 * 3 должно быть равно 6");
    }

    @Test
    void testDivision() {
        assertEquals(2, calculator.divide(6, 3), "6 / 3 должно быть равно 2");
    }

    @Test
    void testDivisionByZero() {
        Exception exception = assertThrows(IllegalArgumentException.class, () -> calculator.divide(5, 0));
        assertEquals("Деление на ноль не допускается", exception.getMessage());
    }
}

Эти тесты проверяют основные арифметические операции и обрабатывают исключение при делении на ноль.


Что оставляет чаще всего людей в замешательстве?

  1. Почему тесты не запускаются? Возможно, ваш метод в тестовом классе не помечен @Test.
  2. Почему "падает" тест? Прочтите сообщение ошибки внимательно. Скорее всего, ожидания assertEquals не совпадают с фактическим результатом.
  3. Как писать тесты к приватным методам? Часто приватные методы тестируются косвенно через публичные.

JUnit 5 — мощный инструмент, и чем больше вы с ним практикуетесь, тем проще становится писать качественные тесты. Вперёд — ломайте свои баги в лучших традициях супергероев!

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ