Ang JUnit ay isang standard framework para sa modular testing sa Java at Kotlin ecosystem, na ginagamit sa Android development upang suriin ang business logic sa antas ng mga isolated component. Ang framework ay nagbibigay ng set ng mga annotation, assertion method, at Test Runner para sa automatic detection at execution ng mga test. Ayon sa JUnit.org, ang library ay nananatiling pinakasikat na solusyon para sa unit testing sa JVM ecosystem: higit sa 70% ng Java projects ay gumagamit ng JUnit sa anumang bersyon.
Mga Pangunahing
JUnit ay isang open-source framework para sa pagsulat at pagpapatakbo ng mga repeatable unit test sa Java at Kotlin. Ito ay bahagi ng xUnit ecosystem — isang pamilya ng frameworks na batay sa arkitektura nina Kent Beck at Erich Gamma, at ito ang standard testing tool sa Android Studio at IntelliJ IDEA.
Ang pangunahing gawain ng JUnit ay ihiwalay ang maliit na bahagi ng code (method, class) at suriin ang behavior nito sa kontroladong kondisyon. Ang mga test ay isinulat bilang ordinaryong Java/Kotlin classes na may mga annotation, at ang framework ang bahala sa detection ng tests, pamamahala ng kanilang lifecycle, at pagkolekta ng execution statistics.
Ang unang bersyon ng JUnit ay lumabas noong 1997 at radikal na binago ang approach sa development, na pinasikat ang Test-Driven Development (TDD) practices. Ngayon, ang JUnit 5 (Jupiter) ang kasalukuyang bersyon, ganap na redesigned na may modular architecture at suporta para sa Java 8+ at extensions.
Ang mekanismo ng JUnit execution ay batay sa Test Runner pattern, na nag-scan ng classpath, nakakahanap ng methods na may @Test annotation, lumilikha ng instance ng test class, at pinapatakbo ang methods sa partikular na order. Test Runner ang namamahala sa lifecycle: tawag BeforeAll → BeforeEach → Test → AfterEach → AfterAll.
Binabalot ng JUnit ang bawat test method sa hiwalay na instance ng class, na ginagarantiyahan ang isolation sa pagitan ng tests. Ibig sabihin nito, ang fields ng class ay hindi nagpapanatili ng state sa pagitan ng iba’t ibang @Test methods — bawat test ay nagsisimula sa malinis na object.
Ang pinakasimpleng test sa JUnit ay mukhang isang method na may @Test annotation, kung saan tinatawag ang code na sinusuri at ang resulta ay sinusuri sa pamamagitan ng assertion. Kung ang assertion ay hindi pumasa — ang test ay itinuturing na failed, at nag-uulat ang JUnit ng error.
@Test
void additionShouldReturnCorrectSum() {
var calculator = new Calculator();
var result = calculator.add(2, 3);
assertEquals(5, result);
}
Awtomatikong hinahanap ng Test Runner ang ganitong method, pinapatakbo ito, at iniuulat ang resulta. Kung ang method ay hindi nag-throw ng exception — pumasa ang test (green). Kung ang assertion ay hindi gumana — bumagsak ang test (red).
Ang mga annotation ng JUnit ay tumutukoy kung kailan at paano dapat isagawa ang test code. Sa JUnit 5, ang mga annotation ay nasa package na org.junit.jupiter.api at sumasaklaw sa lahat ng yugto: paghahanda ng data, pag-execute ng test, paglilinis ng resources.
| Annotation | Layunin | Pag-execute |
|---|---|---|
| @Test | Nagmamarka ng test method | Isang beses kada tawag |
| @BeforeEach | Paghahanda bago ang bawat test | Bago ang bawat @Test |
| @BeforeAll | Isang beses na initialization ng class | Isang beses bago ang lahat ng tests |
| @AfterEach | Paglilinis pagkatapos ng bawat test | Pagkatapos ng bawat @Test |
| @AfterAll | Isang beses na pagsasara ng class | Isang beses pagkatapos ng lahat ng tests |
| @DisplayName | Nababasang pangalan ng test | Dekorasyon |
Tingnan natin ang kumpletong test class na may tamang lifecycle. Ang method na setUp ay lumilikha ng bagong instance ng Calculator bago ang bawat test, at ang tearDown ay nagpapalaya ng resources — halimbawa, pagsasara ng file descriptors o database connections.
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();
}
}
Ang mga Assertion ay static methods na nagkukumpara ng aktwal na resulta sa inaasahan at nag-throw ng exception kung hindi tugma. Ang JUnit 5 ay nag-aalok ng class na org.junit.jupiter.api.Assertions na may higit sa 25 methods para sa iba’t ibang scenario ng pagsusuri — mula sa simpleng paghahambing ng values hanggang sa pagsusuri ng timeouts at group assertions.
Ang method na assertThrows ay nararapat ng espesyal na atensyon — pinapayagan nitong suriin kung ang code ay wastong humahawak ng mga error situation — paghahati sa zero, pagpasa ng null, paglampas sa limits.
@Test
void divisionByZeroShouldThrowException() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Ang Parameterized Tests ay nagbibigay-daan na patakbuhin ang parehong test method na may iba’t ibang set ng arguments. Sa JUnit 5, ginagamit ang annotation na @ParameterizedTest sa kombinasyon ng data source — @ValueSource, @CsvSource, @MethodSource, o @EnumSource.
Ang approach na ito ay radikal na nagbabawas ng code duplication: sa halip na sampung identical tests para sa iba’t ibang values, isang parameterized method ang isinulat. Ayon sa Google Testing Blog, ang parameterization ay nagbabawas ng volume ng test code ng 40–60% nang walang pagkawala ng coverage.
Ang annotation na @CsvSource ay nagpapadala ng ilang rows na may comma separator sa test. Ang bawat row ay tumutugma sa isang execution ng test. Awtomatikong kino-convert ng JUnit ang string values sa kinakailangang types: int, long, String at iba pa.
@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);
}
Kapag ang input data ay mas complex kaysa sa simpleng numbers o strings, ginagamit ang @MethodSource. Ito ay tumutukoy sa static method na nagbabalik ng Stream ng arguments — halimbawa, Stream of Arguments o Stream ng User objects para sa pagtest ng DAO layer.
Sa Android development, ang JUnit ay ginagamit kasama ng AndroidX Test, na nagbibigay ng extensions para sa pagtest ng Activity, Content Provider at iba pang Android components. Ang JUnit ay responsable para sa unit tests na isinasagawa sa JVM nang walang emulator, at ang AndroidX Test para sa instrumental tests sa device.
Para ikonekta ang JUnit 5 sa Android project, sapat na idagdag ang dependency na org.junit.jupiter:junit-jupiter sa build.gradle sa antas ng module. Ang AGP Gradle plugin ay sumusuporta sa pagpapatakbo ng JUnit 5 tests sa JVM sa pamamagitan ng standard 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")
}
Sa praktika, ang JUnit ay madalas na ginagamit para sa pagtest ng ViewModel at repositories — layers na hindi nangangailangan ng Android context o emulator. Ang ganitong test ay isinasagawa sa milliseconds at maaaring patakbuhin nang daang beses nang walang pagkawala ng oras.
JUnit 5 (Jupiter) ay hindi lang bagong version, kundi ganap na redesigned na platform na nahahati sa tatlong modules: JUnit Platform (pagpapatakbo ng tests sa JVM), JUnit Jupiter (API para sa pagsulat ng tests) at JUnit Vintage (backward compatibility sa JUnit 4). Ang modularity na ito ay nagbibigay-daan na magkonekta ng iba’t ibang Test Engine — halimbawa, Spek para sa Kotlin o TestNG.
| Katangian | JUnit 4 | JUnit 5 |
|---|---|---|
| Package | org.junit | org.junit.jupiter |
| Base annotation | @Test (mula junit.framework) | @Test (mula org.junit.jupiter.api) |
| Before/After | @Before, @After, @BeforeClass | @BeforeEach, @AfterEach, @BeforeAll |
| Parameterized | @RunWith(Parameterized.class) | @ParameterizedTest + @ValueSource |
| Extension | @Rule, @ClassRule | @ExtendWith, mas flexible API |
| Java min | Java 5 | Java 8+ |
Ang migration mula JUnit 4 patungong JUnit 5 ay hindi nangangailangan ng pagsulat muli ng lahat ng tests — sapat na ikonekta ang JUnit Vintage Engine, at magpapatuloy ang mga lumang tests na gumana. Ang mga bagong tests ay inirerekomenda na isulat sa JUnit 5 upang samantalahin ang extensions, lambdas sa assertions, at built-in na suporta para sa parameterization.
Mga Madalas Itanong
JUnit ay framework para sa pagsulat at pagpapatakbo ng tests, at ang Mockito ay library para sa paggawa ng mock objects. Ginagamit ang mga ito nang magkasama: pinangangasiwaan ng JUnit ang execution ng test, at pinapalitan ng Mockito ang dependencies ng class na sinusuri.
Oo, ang JUnit 5 ay ganap na compatible sa Android projects. Para sa unit tests, sapat na idagdag ang dependency na junit-jupiter sa build.gradle. Ang instrumental tests ay patuloy na gumagana sa pamamagitan ng AndroidX Test Runner.
Minimum, sapat na ang isang @Test annotation bago ang method. Para sa initialization at cleanup, inirerekomenda ang @BeforeEach at @AfterEach, ngunit hindi ito sapilitan.
Test Runner ay ang component ng JUnit na nag-scan ng classpath, nakakahanap ng methods na may @Test annotation, lumilikha ng instances ng test classes, at pinapatakbo ang tests. Sa JUnit 5, ang role na ito ay ginagampanan ng JUnit Platform na may konektadong Test Engines.
Gamitin ang assertThrows(Class, Executable) — tinatanggap nito ang type ng inaasahang exception at lambda na may tawag ng method. Sinusuri ng JUnit kung ang exception ay talagang na-throw at ibinabalik ito para sa karagdagang pagsusuri.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din