yoklateknik mülakat

Backend Java Testing Tooling Mülakat Soruları

75 doğrulanmış Backend Java Testing Tooling mülakat sorusu — cevaplarıyla çöz, açıklamalarıyla öğren, gerçek simülasyonda kendini test et.

Gerçek simülasyonu dene →

Örnek sorular

Java Testing ToolingZorluk 1
JUnit 5'te bir metodun test runner tarafından bulunup çalıştırılması için ne gerekir?
  • aMetot adı test kelimesiyle başlamalıdır; JUnit 5 hâlâ JUnit 3'teki gibi isimlendirme kuralına dayanır
  • bMetot @Test (ya da @ParameterizedTest gibi test kaydeden ilişkili bir annotation) ile işaretlenmelidir
  • cMetot, runner'ın test instance'ı oluşturmadan çağırabilmesi için public static olarak tanımlanmalıdır
  • dSınıf, metodu JUnit 5 keşif motoruna açan bir Testable arayüzünü implement etmelidir
Açıklama:JUnit 5 testleri isimlendirme kuralıyla değil, tamamen annotation ile keşfeder. @Test (ya da @ParameterizedTest, @RepeatedTest vb.) ile işaretlenmiş bir metot test olarak kaydedilir. Zorunlu bir isim öneki yoktur, public static şartı yoktur (instance metotları kullanılır, package-private yeterlidir) ve implement edilecek bir Testable arayüzü yoktur.
Java Testing ToolingZorluk 2
class CounterTest {
    int count;

    @BeforeEach
    void setUp() {
        count = 10;
        System.out.println("setUp");
    }

    @Test
    void increments() {
        count++;
        System.out.println("test:" + count);
    }

    @AfterEach
    void tearDown() {
        System.out.println("tearDown:" + count);
    }
}

increments() çalıştığında ne yazdırılır?
  • asetUp, test:11, tearDown:11 — çünkü @BeforeEach testten önce, @AfterEach sonra çalışır ve aynı instance state'ini paylaşırlar
  • btest:11, setUp, tearDown:10 — çünkü JUnit önce annotation'lı test metodunu çalıştırır, lifecycle hook'larını sadece temizlik için sonradan sarar
  • csetUp, test:11, tearDown:0 — çünkü @AfterEach yazdırmadan önce alanı yeniden başlatılmış hâliyle çalışır
  • dsetUp, tearDown:10, test:11 — çünkü @AfterEach, alanı yazdırmadan önce test-öncesi değerine geri döndürür
Açıklama:Her @Test metodu için JUnit 5 önce @BeforeEach'i, sonra testin kendisini, sonra @AfterEach'i çalıştırır — hepsi AYNI test instance'ı üzerinde, dolayısıyla alan durumu aralarında taşınır. setUp, count = 10 yapar ve setUp yazdırır. Test 11'e artırır ve test:11 yazdırır. tearDown sonra o anki count'u yazdırır, bu hâlâ 11'dir, yani tearDown:11 çıkar.
Java Testing ToolingZorluk 2
@Test
void checksTotal() {
    int actualTotal = computeTotal(); // 7 döner
    assertEquals(actualTotal, 10);
}

Test başarısız oluyor. Hata mesajı ne rapor eder?
  • a"expected: <7> but was: <10>" — çünkü assertEquals'a geçilen ilk argüman expected sayılır ve burada yanlışlıkla önce actualTotal (7) geçilmiştir
  • b"expected: <10> but was: <7>" — çünkü JUnit argüman sırasından bağımsız olarak her zaman küçük sayısal değeri actual olarak etiketler
  • cDerleme hatası oluşur, çünkü assertEquals literal expected değerinin ikinci argüman olarak geçilmesini zorunlu kılar
  • d"expected: <10> but was: <10>" — çünkü JUnit raporlamadan önce iki argümanı da aynı karşılaştırma hedefine indirger
Açıklama:assertEquals(expected, actual) sadece POZİSYONA göre birinci argümanı "expected", ikincisini "actual" sayar — hangi değişken adının ne anlama geldiğini bilmez. Buradaki çağrı assertEquals(actualTotal, 10) olduğundan JUnit actualTotal'ı (7) expected, 10'u actual olarak raporlar: "expected: <7> but was: <10>". Bu yaygın bir junior hatasıdır — argümanlar ters geçilmiştir, bu testin geçip geçmemesini değiştirmez ama yanıltıcı bir mesaj üretir.
Java Testing ToolingZorluk 2
@Test
void rejectsNegativeAmount() {
    Account acc = new Account();
    IllegalArgumentException ex = assertThrows(
        IllegalArgumentException.class,
        () -> acc.withdraw(-5)
    );
    assertEquals("amount must be positive", ex.getMessage());
}

assertThrows burada ne döner ve bu neden faydalıdır?
  • avoid döner; ex aslında lambda çalıştıktan sonra JUnit'in doldurduğu gizli bir static alandan atanır ve test bunu okur
  • bException'ın fırlatılıp fırlatılmadığını gösteren bir boolean döner, ex de kolaylık için exception tipine otomatik cast edilir
  • cLambda'nın (Executable) kendisini döner, bu da testin acc.withdraw(-5)'i tekrar çağırıp exception'ı incelemesine izin verir
  • dYakalanan exception instance'ını (IllegalArgumentException tipinde) döner, bu da testin mesaj gibi ayrıntılar üzerinde ek assertion yapmasına izin verir
Açıklama:assertThrows(expectedType, executable) executable'ı çalıştırır, expectedType'a atanabilir bir exception fırlattığını doğrular ve yakalanan bu exception'ı (zaten expectedType'a cast edilmiş olarak) döner. Bu, testin "bir exception fırlatıldı" ötesine geçip ex.getMessage() ya da ex.getCause() gibi detaylar üzerinde assertion yapmasını sağlar. Exception fırlatılmazsa ya da yanlış tip fırlatılırsa assertThrows'un kendisi testi başarısız yapar.
Java Testing ToolingZorluk 1
@Test
void parsesConfig() {
    Config c = Config.parse("invalid"); // içeride NumberFormatException fırlatır
    assertNotNull(c);
}

Config.parse("invalid"), testin yakalamadığı unchecked bir NumberFormatException fırlatırsa teste ne olur?
  • aTest geçer, çünkü JUnit sadece assertNotNull'ı değerlendirir ve ondan önce fırlatılan bir exception'a asla ulaşmaz
  • bTest başarısız/hatalı olur, çünkü @Test metodundan dışarı sızan HERHANGİ bir exception JUnit runner tarafından yakalanıp test başarısızlığı olarak raporlanır
  • cTest atlanır (skip), çünkü JUnit yakalanmamış runtime exception'ları @Disabled ile aynı şekilde ele alır
  • dBuild hemen durur ve sınıftaki ya da suite'teki başka hiçbir test metodu çalıştırılmaz
Açıklama:Bir @Test metodunun bir exception'da başarısız olması için assertThrows'a ihtiyacı yoktur — test metodundan dışarı sızan HERHANGİ bir exception (checked ya da unchecked) JUnit runner tarafından yakalanır ve başarısız/hatalı test olarak raporlanır. Bu durumda assertNotNull'a hiç ulaşılmaz. Sınıftaki ve suite'teki diğer testler yine de çalışır; JUnit başarısızlıkları test metodu bazında izole eder.
Java Testing ToolingZorluk 2
interface PaymentGateway {
    boolean charge(String cardId, int amountCents);
    String lastTransactionId();
}

@Test
void unstubbedMockReturnsDefaults() {
    PaymentGateway gw = mock(PaymentGateway.class);

    boolean result = gw.charge("card-1", 500);
    String txId = gw.lastTransactionId();

    assertFalse(result);
    assertNull(txId);
}

Herhangi bir when(...).thenReturn(...) stub'ı olmadan bu test neden geçer?
  • aGeçmez — stub'lanmamış bir Mockito mock üzerinde herhangi bir metot çağırmak runtime'da UnnecessaryStubbingException fırlatır
  • bMockito çağrıları kaydeder ama classpath'te bulunan gerçek PaymentGateway implementasyonunu tekrar oynatır, bu da bu girdiler için false/null döner
  • cBir Mockito mock, stub'lanmamış metotlar için dönüş tipine uygun varsayılan değerler döner — boolean için false, obje dönüş tipleri için null, sayısal tipler için 0
  • dMock, ilk stub'lanmamış çağrıda NullPointerException fırlatır, test framework'ü bunu sessizce geçen bir assertion'a çevirir
Açıklama:mock(...) ile oluşturulan bir Mockito mock varsayılan olarak HİÇBİR gerçek davranışa sahip değildir. when(...).thenReturn(...) ile stub'lanmamış herhangi bir metot çağrısı için Mockito dönüş tipine göre makul bir varsayılan döner: boolean için false, sayısal primitifler için 0/0.0, obje referansları için (String dahil) null, koleksiyon dönüş tipleri için boş koleksiyon. Sadece stub'lanmamış bir metodu çağırmak hiçbir exception fırlatmaz.

3300 soruluk Backend bankasında kendini sına.

Mülakata başla