JUnit, Java ve Kotlin ekosisteminde birim testleri için standart bir framework olup, Android geliştirmede izole edilmiş bileşenler düzeyinde iş mantığını doğrulamak için kullanılır. Framework, testleri otomatik olarak bulmak ve yürütmek için bir dizi ek açıklama, assertion yöntemi ve Test Runner sağlar. JUnit.org'a göre, kütüphane JVM ekosisteminde birim testleri için en popüler çözüm olmaya devam etmektedir: Java projelerinin %70'inden fazlası herhangi bir sürümde JUnit kullanmaktadır.
Anahtar Noktalar
JUnit, Java ve Kotlin'de tekrarlanabilir birim testleri yazmak ve çalıştırmak için açık kaynaklı bir frameworktür. Kent Beck ve Erich Gamma'nın mimarisine dayanan xUnit ekosisteminin bir parçasıdır ve Android Studio ile IntelliJ IDEA'da standart test aracıdır.
JUnit'in ana görevi, küçük bir kod parçasını (metot, sınıf) izole etmek ve kontrollü koşullar altında davranışını doğrulamaktır. Testler, ek açıklamalarla birlikte normal Java/Kotlin sınıfları olarak yazılır ve framework, test bulma, yaşam döngüsü yönetimi ve yürütme istatistikleri toplama işlemlerini üstlenir.
JUnit'in ilk sürümü 1997'de ortaya çıktı ve Test Güdümlü Geliştirme (TDD) uygulamalarını popülerleştirerek geliştirme yaklaşımını kökten değiştirdi. Bugün, JUnit 5 (Jupiter), Java 8+ ve uzantıları destekleyen modüler bir mimariyle tamamen yeniden tasarlanmış güncel sürümdür.
JUnit yürütme mekanizması, classpath'i tarayan, @Test ek açıklamasına sahip metotları bulan, test sınıfının bir örneğini oluşturan ve metotları belirli bir sırayla çalıştıran Test Runner desenine dayanır. Test Runner, yaşam döngüsünü yönetir: BeforeAll → BeforeEach → Test → AfterEach → AfterAll.
JUnit, her test metodunu ayrı bir sınıf örneğine sararak testler arasında izolasyon sağlar. Bu, sınıf alanlarının farklı @Test metotları arasında durum korumadığı anlamına gelir — her test temiz bir nesneyle başlar.
JUnit'teki en basit test, @Test ek açıklamasına sahip, test edilen kodu çağıran ve bir assertion kullanarak sonucu doğrulayan bir metottur. Assertion başarısız olursa, test başarısız sayılır ve JUnit hatayı bildirir.
@Test
void additionShouldReturnCorrectSum() {
var calculator = new Calculator();
var result = calculator.add(2, 3);
assertEquals(5, result);
}
Test Runner, böyle bir metodu otomatik olarak bulur, çalıştırır ve sonucu bildirir. Metot bir istisna fırlatmazsa — test geçer (green). Bir assertion başarısız olursa — test başarısız olur (red).
JUnit'teki ek açıklamalar, test kodunun ne zaman ve nasıl yürütüleceğini tanımlar. JUnit 5'te, ek açıklamalar org.junit.jupiter.api paketinde bulunur ve tüm aşamaları kapsar: veri hazırlığı, test yürütme, kaynak temizliği.
| Ek Açıklama | Amaç | Yürütme |
|---|---|---|
| @Test | Bir test metodunu işaretler | Her çağrıda bir kez |
| @BeforeEach | Her testten önce hazırlık | Her @Test'ten önce |
| @BeforeAll | Sınıfın bir kerelik başlatılması | Tüm testlerden önce bir kez |
| @AfterEach | Her testten sonra temizlik | Her @Test'ten sonra |
| @AfterAll | Sınıfın bir kerelik tamamlanması | Tüm testlerden sonra bir kez |
| @DisplayName | Okunabilir test adı | Süsleme |
Uygun bir yaşam döngüsüne sahip tam bir test sınıfı düşünelim. setUp metodu, her testten önce yeni bir Calculator örneği oluşturur ve tearDown, kaynakları serbest bırakır — örneğin, dosya tanımlayıcılarını veya veritabanı bağlantılarını kapatmak.
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, gerçek sonucu beklenen sonuçla karşılaştıran ve eşleşmezse bir istisna fırlatan statik metotlardır. JUnit 5, basit değer karşılaştırmasından zaman aşımı kontrollerine ve gruplandırılmış assertionlara kadar çeşitli doğrulama senaryoları için 25'ten fazla metoda sahip org.junit.jupiter.api.Assertions sınıfını sunar.
assertThrows metodu, kodun sıfıra bölme, null geçirme, sınır aşımı gibi hata durumlarını doğru şekilde ele alıp almadığını doğrulamaya olanak tanıdığı için özel ilgiyi hak eder.
@Test
void divisionByZeroShouldThrowException() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Parametrelenmiş testler, aynı test metodunun farklı argüman kümeleriyle çalıştırılmasına olanak tanır. JUnit 5'te bu, @ParameterizedTest ek açıklamasının bir veri kaynağıyla (@ValueSource, @CsvSource, @MethodSource veya @EnumSource) birleştirilmesiyle yapılır.
Bu yaklaşım, kod tekrarını kökten azaltır: farklı değerler için on özdeş test yazmak yerine, tek bir parametrelenmiş metot yazılır. Google Testing Blog'a göre, parametrelendirme, kapsamı kaybetmeden test kodu hacmini %40–60 oranında azaltır.
@CsvSource ek açıklaması, teste virgülle ayrılmış birden çok satır iletir. Her satır, bir test çalıştırmasına karşılık gelir. JUnit, dize değerlerini otomatik olarak gerekli türlere (int, long, String ve diğerleri) dönüştürür.
@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);
}
Giriş verileri basit sayı veya dizelerden daha karmaşık olduğunda @MethodSource kullanılır. Bir argüman Stream'i döndüren statik bir metoda başvurur — örneğin, DAO katmanını test etmek için bir Arguments Stream'i veya User nesnelerinin Stream'i.
Android geliştirmede, JUnit, Activity, Content Provider ve diğer Android bileşenlerini test etmek için uzantılar sağlayan AndroidX Test ile birlikte kullanılır. JUnit, öykünücü olmadan JVM'de yürütülen birim testlerini yönetirken, AndroidX Test cihazda araçsal testleri yönetir.
Bir Android projesine JUnit 5 eklemek için, modül düzeyindeki build.gradle dosyasına org.junit.jupiter:junit-jupiter bağımlılığını eklemek yeterlidir. AGP Gradle eklentisi, standart Test Runner aracılığıyla JVM'de JUnit 5 testlerinin çalıştırılmasını destekler.
// 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")
}
Pratikte, JUnit en çok Android bağlamı veya öykünücü gerektirmeyen katmanlar olan ViewModel ve havuzları test etmek için kullanılır. Böyle bir test milisaniyeler içinde çalışır ve zaman kaybetmeden yüzlerce kez yürütülebilir.
JUnit 5 (Jupiter) sadece yeni bir sürüm değil, üç modüle ayrılmış tamamen yeniden tasarlanmış bir platformdur: JUnit Platform (JVM'de test yürütme), JUnit Jupiter (test yazmak için API) ve JUnit Vintage (JUnit 4 ile geriye dönük uyumluluk). Bu modülerlik, farklı Test Engine'lerin (örneğin, Kotlin için Spek veya TestNG) bağlanmasına olanak tanır.
| Özellik | JUnit 4 | JUnit 5 |
|---|---|---|
| Paket | org.junit | org.junit.jupiter |
| Temel ek açıklama | @Test (junit.framework'tan) | @Test (org.junit.jupiter.api'den) |
| Before/After | @Before, @After, @BeforeClass | @BeforeEach, @AfterEach, @BeforeAll |
| Parametrelenmiş | @RunWith(Parameterized.class) | @ParameterizedTest + @ValueSource |
| Uzantı | @Rule, @ClassRule | @ExtendWith, daha esnek API |
| Java min | Java 5 | Java 8+ |
JUnit 4'ten JUnit 5'e geçiş, tüm testlerin yeniden yazılmasını gerektirmez — sadece JUnit Vintage Engine'i ekleyin ve eski testler çalışmaya devam edecektir. Yeni testlerin, uzantılardan, lambda assertionlarından ve yerleşik parametrelendirme desteğinden yararlanmak için JUnit 5 ile yazılması önerilir.
Sıkça sorulan sorular
JUnit test yazmak ve çalıştırmak için bir framework iken, Mockito mock nesneler oluşturmak için bir kütüphanedir. Birlikte kullanılırlar: JUnit test yürütmesini yönetir, Mockito ise test edilen sınıfın bağımlılıklarını değiştirir.
Evet, JUnit 5 Android projeleriyle tamamen uyumludur. Birim testleri için, build.gradle dosyasına junit-jupiter bağımlılığını eklemek yeterlidir. Araçsal testler, AndroidX Test Runner aracılığıyla çalışmaya devam eder.
Minimumda, metottan önce tek bir @Test ek açıklaması yeterlidir. Başlatma ve temizlik için @BeforeEach ve @AfterEach önerilir, ancak zorunlu değildir.
Test Runner, classpath'i tarayan, @Test ek açıklamasına sahip metotları bulan, test sınıflarının örneklerini oluşturan ve testleri çalıştıran bir JUnit bileşenidir. JUnit 5'te bu rol, bağlı Test Engine'ler ile JUnit Platform tarafından üstlenilir.
assertThrows(Class, Executable) kullanın — beklenen istisna türünü ve metot çağrısını içeren bir lambda alır. JUnit, istisnanın gerçekten fırlatıldığını doğrular ve daha fazla inceleme için onu döndürür.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun