JUnit је стандардни оквир за модулно тестирање у екосистему Java и Kotlin, који се користи у Android развоју за проверу пословне логике на нивоу изолованих компонената. Оквир пружа скуп анотација, assertion метода и Test Runner-а за аутоматско откривање и извршавање тестова. Према JUnit.org, библиотека остаје најпопуларније решење за јединично тестирање у JVM екосистему: више од 70% Java пројеката користи JUnit у било којој верзији.
Главно
JUnit је оквир отвореног кода за писање и покретање поновљивих јединичних тестова на Java и Kotlin језицима. Улази у екосистем xUnit — породицу оквира заснованих на архитектури Kent Beck-а и Erich Gamma-а, и представља стандардни алат за тестирање у Android Studio и IntelliJ IDEA.
Основни задатак JUnit-а је да изолује мали део кода (методу, класу) и провери његово понашање у контролисаним условима. Тестови се пишу као обичне Java/Kotlin класе са анотацијама, а оквир преузима откривање тестова, управљање њиховим животним циклусом и прикупљање статистике извршавања.
Прва верзија JUnit-а појавила се 1997. године и радикално је променила приступ развоју, популаришући праксе Test-Driven Development (TDD). Данас је JUnit 5 (Jupiter) актуелна верзија, потпуно прерађена у модулну архитектуру са подршком за Java 8+ и проширења.
Механизам извршавања JUnit-а заснован је на обрасцу Test Runner, који скенира classpath, проналази методе са анотацијом @Test, креира инстанцу тест класе и покреће методе одређеним редоследом. Test Runner управља животним циклусом: позив BeforeAll → BeforeEach → Test → AfterEach → AfterAll.
JUnit омотава сваку тест методу у посебну инстанцу класе, што гарантује изолацију између тестова. То значи да поља класе не чувају стање између различитих @Test метода — сваки тест почиње са чистим објектом.
Најједноставнији тест у JUnit-у изгледа као метода са анотацијом @Test, у којој се позива тестирани код и проверава резултат кроз assertion. Ако assertion не прође — тест се сматра неуспешним и JUnit пријављује грешку.
@Test
void additionShouldReturnCorrectSum() {
var calculator = new Calculator();
var result = calculator.add(2, 3);
assertEquals(5, result);
}
Test Runner аутоматски проналази такву методу, покреће је и пријављује резултат. Ако метода не баца изузетак — тест је прошао (green). Ако assertion не успева — тест пада (red).
Анотације JUnit-а одређују када и како тестни код треба да се извршава. У JUnit 5 анотације се налазе у пакету org.junit.jupiter.api и покривају све фазе: припрему података, извршавање теста, чишћење ресурса.
| Анотација | Намена | Извршава се |
|---|---|---|
| @Test | Означава тест методу | Једном по позиву |
| @BeforeEach | Припрема пре сваког теста | Пре сваког @Test |
| @BeforeAll | Једнократна иницијализација класе | Једном пре свих тестова |
| @AfterEach | Чишћење после сваког теста | После сваког @Test |
| @AfterAll | Једнократно завршавање класе | Једном после свих тестова |
| @DisplayName | Човеку разумљив назив теста | Декорација |
Размотримо пуну тест класу са исправним животним циклусом. Метода setUp креира свежу инстанцу Calculator-а пре сваког теста, а tearDown ослобађа ресурсе — на пример, затвара дескрипторе датотека или везе са базом података.
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator();
}
@Test
void subtractionShouldReturnCorrectResult() {
int result = calculator.subtract(10, 4);
assertEquals(6, result);
}
@AfterEach
void tearDown() {
calculator.reset();
}
}
Assertions су статичке методе које пореде стварни резултат са очекиваним и бацају изузетак при непоклапању. JUnit 5 нуди класу org.junit.jupiter.api.Assertions са више од 25 метода за различите сценарије провере — од једноставног поређења вредности до провере временских ограничења и групних assertion-а.
Посебну пажњу заслужује метода assertThrows која омогућава проверу да код исправно обрађује грешке ситуације — дељење нулом, прослеђивање null, прекорачивање лимита.
@Test
void divisionByZeroShouldThrowException() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Параметризовани тестови омогућавају покретање исте тест методе са различитим скуповима аргумената. У JUnit 5 за то се користи анотација @ParameterizedTest у комбинацији са извором података — @ValueSource, @CsvSource, @MethodSource или @EnumSource.
Овај приступ радикално смањује дуплирање кода: уместо десет идентичних тестова за различите вредности пише се једна параметризована метода. Према Google Testing Blog-u, параметризација смањује обим тест кода за 40–60% без губитка покривености.
Анотација @CsvSource преноси у тест више редова са зарезом као раздвајачем. Сваки ред одговара једном покретању теста. JUnit аутоматски претвара вредности низи у потребне типове: int, long, String и друге.
@ParameterizedTest
@CsvSource({
"1, 1, 2",
"2, 3, 5",
"10, 20, 30",
"-1, 1, 0"
})
void additionWithMultipleInputs(int a, int b, int expected) {
assertEquals(expected, a + b);
}
Када су улазни подаци сложенији од једноставних бројева или низи, користи се @MethodSource. Он се позива на статичку методу која враћа Stream аргумената — на пример, Stream of Arguments или Stream User објеката за тестирање DAO слоја.
У Android развоју JUnit се користи у пару са AndroidX Test, који пружа проширења за тестирање Activity, Content Provider-а и других Android компонената. JUnit је задужан за јединичне тестове (unit tests) који се извршавају на JVM-у без емулатора, а AndroidX Test за инструменталне тестове на уређају.
За повезивање JUnit 5 у Android пројекат довољно је додати зависност org.junit.jupiter:junit-jupiter у build.gradle на нивоу модула. AGP Gradle прикључак подржава покретање JUnit 5 тестова на JVM-у кроз стандардни Test Runner.
// build.gradle.kts
android {
testOptions {
unitTests.isIncludeAndroidResources = true
}
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
testImplementation("androidx.test:core-ktx:1.6.1")
}
У пракси, JUnit се најчешће користи за тестирање ViewModel-а и репозиторијума — слојева који не захтевају Android контекст или емулатор. Такав тест се извршава у милисекундама и може да се покреће стотинама пута без губитка времена.
JUnit 5 (Jupiter) није само нова верзија, већ потпуно прерађена платформа подељена на три модула: JUnit Platform (покретање тестова на JVM-у), JUnit Jupiter (API за писање тестова) и JUnit Vintage (уназад компатибилност са JUnit 4). Оваква модулност омогућава повезивање различитих Test Engine-а — на пример, Spek за Kotlin или TestNG.
| Карактеристика | JUnit 4 | JUnit 5 |
|---|---|---|
| Пакет | org.junit | org.junit.jupiter |
| Основна анотација | @Test (из junit.framework) | @Test (из org.junit.jupiter.api) |
| Before/After | @Before, @After, @BeforeClass | @BeforeEach, @AfterEach, @BeforeAll |
| Parameterized | @RunWith(Parameterized.class) | @ParameterizedTest + @ValueSource |
| Extension | @Rule, @ClassRule | @ExtendWith, флексибилнији API |
| Java min | Java 5 | Java 8+ |
Миграција са JUnit 4 на JUnit 5 не захтева преписивање свих тестова — довољно је повезати JUnit Vintage Engine, и стари тестови ће наставити да раде. Нове тестове препоручује се писати у JUnit 5 да би се користили проширења, ламбде у assertion-има и уграђена подршка за параметризацију.
Често постављана питања
JUnit је оквир за писање и покретање тестова, а Mockito је библиотека за креирање mock објеката. Користе се заједно: JUnit управља извршавањем теста, а Mockito замењује зависности тестиране класе.
Да, JUnit 5 је потпуно компатибилан са Android пројектима. За јединичне тестове довољно је додати зависност junit-jupiter у build.gradle. Инструментални тестови и даље раде кроз AndroidX Test Runner.
Минимално је довољна једна анотација @Test пре методе. За иницијализацију и чишћење препоручују се @BeforeEach и @AfterEach, али нису обавезне.
Test Runner је компонента JUnit-а која скенира classpath, проналази методе са анотацијом @Test, креира инстанце тест класа и покреће тестове. У JUnit 5 ову улогу испуњава JUnit Platform са повезаним Test Engine-има.
Користите assertThrows(Class, Executable) — прихвата тип очекиваног изузетка и ламбду са позивом методе. JUnit проверава да ље изузетак стварно бачен и враћа га за додатну проверу.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође