Первый тест
Тест — обычный метод в обычном классе, помеченный аннотацией @Test. JUnit находит такие методы, создаёт объект класса и вызывает их по очереди. Внутри метода вы вызываете свой код и сравниваете результат с ожидаемым. Если значения разошлись, проверка выбрасывает ошибку, и тест считается упавшим.
Тестовый класс
Создайте src/test/java/com/example/shop/PriceCalculatorTest.java — в IDE через «New → Java Class» в папке src/test/java или действием «Create Test» в IntelliJ IDEA на классе PriceCalculator:
// src/test/java/com/example/shop/PriceCalculatorTest.java
package com.example.shop;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertEquals;
class PriceCalculatorTest {
@Test
void totalMultipliesPriceByQuantity() {
PriceCalculator calculator = new PriceCalculator();
BigDecimal total = calculator.total(new BigDecimal("12.00"), 3);
assertEquals(new BigDecimal("36.00"), total);
}
}Тест проверяет, что 3 товара по $12.00 стоят $36.00. Запустите его командой mvn test:
[INFO] Running com.example.shop.PriceCalculatorTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.073 s -- in com.example.shop.PriceCalculatorTest
[INFO] BUILD SUCCESSИз чего он состоит
| Часть | Смысл |
|---|---|
class PriceCalculatorTest | Имя — проверяемый класс плюс Test: так Surefire находит тестовые классы |
@Test | Помечает метод как тест |
void, без параметров | Тест ничего не возвращает |
assertEquals(expected, actual) | Первым идёт ожидаемое значение, вторым — фактическое |
import static | Позволяет писать assertEquals без Assertions. впереди |
Ни классу, ни методу не нужен public: достаточно пакетного доступа.
Подготовка, действие, проверка
Пустые строки в тесте стоят не случайно. У хорошего теста три части:
- Подготовка (arrange) — создать объекты и данные: калькулятор.
- Действие (act) — один раз вызвать проверяемый метод:
total(). - Проверка (assert) — сравнить результат:
assertEquals.
По этой схеме любой тест легко читать: что дано, что делаем, что ожидаем.
Второй тест
Каждый случай — отдельный метод. Добавьте в тот же класс проверку скидки:
// src/test/java/com/example/shop/PriceCalculatorTest.java
@Test
void discountReducesAmount() {
PriceCalculator calculator = new PriceCalculator();
BigDecimal result = calculator.applyDiscount(new BigDecimal("50.00"), 10);
assertEquals(new BigDecimal("45.00"), result);
}Теперь mvn test печатает Tests run: 2. Имя метода описывает ожидаемое поведение: когда тест упадёт, по одному имени будет понятно, что сломалось.
Частая ошибка
JUnit не запускает тестовый метод, если он private или возвращает значение. Проект компилируется, а тесты молча пропадают из результатов. JUnit 6 хотя бы предупреждает об этом:
WARNING: TestEngine with ID 'junit-jupiter' encountered 2 non-critical issues during test discovery:
(1) [WARNING] @Test method 'private void com.example.shop.PrivateTest.totalMultipliesPriceByQuantity()' must not be private. It will not be executed.
(2) [WARNING] @Test method 'int com.example.shop.PrivateTest.returnsValue()' must not return a value. It will not be executed.
...
[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0Тестовый метод всегда void и никогда не private.