Soru JUnit 4 testlerinde belirli bir istisnanın atıldığını nasıl iddia ediyorsunuz?


Bazı kodun bir istisna attığını test etmek için JUnit4 deyimsel olarak nasıl kullanabilirim?

Ben kesinlikle böyle bir şey yapabilirken:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

Bir açıklama veya Assert.xyz olduğunu veya bir şey Bu, bu tür durumlar için JUnit'in ruhundan çok daha az ve çok daha fazla bir ruh hali.


1624
2017-10-01 06:56


Menşei


Başka herhangi bir yaklaşımla ilgili problem, ancak istisna atıldıktan sonra bu testin her zaman sona erdirilmesidir. Öte yandan, çoğu kez hala aramak istiyorum org.mockito.Mockito.verify istisna atılmadan önce belirli şeylerin yapıldığından emin olmak için çeşitli parametrelerle (doğru parametrelerle bir logger servisi çağrıldı). - ZeroOne
JUnit wiki sayfasında istisnaların nasıl test edildiğini görebilirsiniz. github.com/junit-team/junit/wiki/Exception-testing - PhoneixS
@ZeroOne - Bunun için iki farklı test olurdu: istisna için bir tane ve alayla etkileşimi doğrulamak için. - tddmonkey
Bunu JUnit 5 ile yapmanın bir yolu var, cevabımı aşağıda güncelledim. - Dilini Rajapaksha


Cevaplar:


JUnit 4 bunun için destek var:

@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);
}

Referans: https://junit.org/junit4/faq.html#atests_7


1945
2017-10-01 07:12



Kodunuzda bir istisna olmasını beklerseniz, bu kod parçası işe yaramaz ve bunun gibi bir battaniye olmaz. - Oh Chin Boon
@skaffman Bu org.junit.experimental.theories.Theory org.junit.experimental.theories.Theories tarafından koşan ile çalışmayacak - Artem Oboturov
Roy Osherove, bu tür İstisna testlerini teşvik ediyor Birim Testi sanatıİstisna testin içinde herhangi bir yerde olabileceğinden ve sadece test edilen birimin içinde olamayacağından. - Kevin Wittek
@ Kiview / Roy Osherove ile katılmıyorum. Benim görüşüme göre, testler, davranış değil, uygulama için olmalıdır. Belirli bir yöntemin bir hata atabileceğini test ederek, testlerinizi doğrudan uygulamaya uygularsınız. Yukarıda gösterilen yöntemde yapılan testlerin daha değerli bir test sağladığını iddia ediyorum. Ekleyeceğim uyarı, bu durumda özel bir istisna için test edeceğim, böylece gerçekten istediğim istisnayı alıyorum. - nickbdyer
Ne. Sınıfın davranışını test etmek istiyorum. Önemli olan, orada olmayan bir şeyi geri almaya çalışırsam, bir istisna almamdır. Veri yapısının olduğu gerçeği ArrayList cevap verir get() Alakasız. Gelecekte ilkel bir diziye geçmek için seçtiysem, bu test uygulamasını değiştirmek zorunda kalırdım. Veri yapısı gizlenmeli, böylece test davranışına odaklanabilir. sınıf. - nickbdyer


Düzenle Şimdi JUnit5 piyasaya çıktı, en iyi seçenek kullanmak olacak Assertions.assertThrows() (görmek diğer cevabım).

JUnit 5'e geçiş yapmadıysanız ancak JUnit 4.7'yi kullanabiliyorsanız, ExpectedException Kural:

public class FooTest {
  @Rule
  public final ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    foo.doStuff();
  }
}

Bu çok daha iyi @Test(expected=IndexOutOfBoundsException.class) çünkü eğer test başarısız olur IndexOutOfBoundsException daha önce atılmış foo.doStuff()

Görmek Bu makale detaylar için


1166
2018-05-29 17:16



@skaffman - Eğer bunu doğru olarak anladım, istisna gibi görünüyor.Öncelikle bir sınıfta değil, sadece bir testte uygulanıyor. - bacar
Eğer atılmasını beklediğimiz istisna, kontrol edilmiş bir istisna ise, bu durumu atmalı mı, denemeli mi yoksa başka bir şekilde mi test etmeliyiz? - MJafar Mash
@MartinTrummer Kural dışı durum atıldığından ve yöntemden çıkıldığından foo.doStuff () öğesinden sonra kod çalıştırılmamalıdır. Beklenen bir istisnadan sonra (sonunda kaynakların kapatılması hariç) kod olması, istisna olursa, hiçbir zaman çalıştırılmaması gerektiğinden, yararsızdır. - Jason Thompson
Bu en iyi yaklaşımdır. Burada skaffman'ın çözümüne kıyasla iki avantaj var. İlk olarak, ExpectedException Sınıfın istisnanın mesajını eşleme yolları vardır, hatta istisna sınıfına bağlı olan kendi eşleştiricinizi yazabilir. İkinci olarak, beklentinizi istisna atmayı beklediğiniz kod satırından hemen önce ayarlayabilirsiniz - yani yanlış kod satırı istisnayı atarsa ​​testiniz başarısız olur; skaffman'ın çözümü ile bunu yapmanın bir yolu yok. - Dawood ibn Kareem
@MJafarMash atmayı beklediğiniz istisna kontrol edilirse, bu istisnayı test yönteminin throws maddesine eklersiniz. Özel durum, belirli bir test vakasında tetiklenmemiş olsa bile, kontrol edilmiş bir istisna attığını bildiren bir yöntemi test ettiğinizde aynı şeyi yaparsınız. - NamshubWriter


Beklenen istisnayı kullanarak dikkatli olun, çünkü sadece yöntem Bu istisnayı attı, bir değil özel kod satırı testte.

Parametre geçerliliğini test etmek için bunu kullanıyorum, çünkü bu yöntemler genellikle çok basittir, ancak daha karmaşık testler aşağıdakilerle daha iyi bir şekilde sunulabilir:

try {
    methodThatShouldThrow();
    fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}

Karar ver.


409
2017-10-01 09:31



Belki ben eski okulum ama yine de bunu tercih ederim. Ayrıca, istisnanın kendisini test etmek için bana bir yer veriyor: bazen belirli değerler için alıcılarla istisnalarım var ya da mesajda belirli bir değeri arayabilirim (örneğin "tanınmayan kod" xyz "mesajında" xyz "yi arıyor olabilir) "). - Rodney Gitzel
Bence NamshubWriter'in yaklaşımı size her iki dünyanın da en iyisini sunuyor. - Eddie
+1 beklenen = xx gereksinimlerinin eşleşmediği bazı senaryolarda yararlıdır. - Oh Chin Boon
ExpectedException kullanarak bu exception.expect (IndexOutOfBoundsException.class) gibi test etmek için yöntem başına N exception.expect öğesini çağırabilirsiniz; foo.doStuff1 (); exception.expect (IndexOutOfBoundsException.class); foo.doStuff2 (); exception.expect (IndexOutOfBoundsException.class); foo.doStuff3 (); - user1154664
@ user1154664 Aslında yapamazsın. ExpectedException'ı kullanarak, yalnızca bir yöntemin bir istisna attığını test edebilirsiniz, çünkü bu yöntem çağrıldığında, test beklenen bir istisna attığından dolayı yürütmeyi durduracaktır! - NamshubWriter


Daha önce cevaplandığı gibi, JUnit'teki istisnalarla uğraşmanın birçok yolu vardır. Ama Java 8 ile başka bir tane var: Lambda İfadeleri'ni kullanıyor. Lambda İfadeleri ile şöyle bir sözdizimi elde edebiliriz:

@Test
public void verifiesTypeAndMessage() {
    assertThrown(new DummyService()::someMethod)
            .isInstanceOf(RuntimeException.class)
            .hasMessage("Runtime exception occurred")
            .hasMessageStartingWith("Runtime")
            .hasMessageEndingWith("occurred")
            .hasMessageContaining("exception")
            .hasNoCause();
}

assertThrown, örnekleri lambda ifadeleri, yöntem referansları veya yapıcı referansları ile oluşturulabilen işlevsel bir arabirimi kabul eder. assertBu arabirimin kabul edilmesini bekliyor ve bir istisnayı ele almaya hazır olacak.

Bu nispeten basit ama güçlü bir tekniktir.

Bu tekniği açıklayan bu blog gönderisine bir göz atın: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

Kaynak kodu burada bulunabilir: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

Açıklama: Blogun ve projenin yazarıyım.


189
2017-07-07 22:35



Bu çözümü beğendim ama bunu bir maven repo'dan indirebilir miyim? - Selwyn
@Arangeuster Maven'de bulunan bu fikrin bir uygulaması stefanbirkner.github.io/vallado - NamshubWriter
Bunu JUnit'e çekme talebi olarak sunmalılar ... - Cristiano Fontes
@CristianoFontes bu API'nin daha basit bir sürümü JUnit 4.13 için kaplıdır. Görmek github.com/junit-team/junit/commit/... - NamshubWriter
@RafalBorowiec teknik olarak new DummyService()::someMethod bir MethodHandleama bu yaklaşım lambda ifadeleriyle eşit derecede iyi çalışır. - Andy


cunette, istisnai test etmek için dört yol var.

  • junit4.x için, Test anvanmasının isteğe bağlı 'beklenen' özelliğini kullanın

    @Test(expected = IndexOutOfBoundsException.class)
    public void testFooThrowsIndexOutOfBoundsException() {
        foo.doStuff();
    }
    
  • junit4.x için ExpectedException kuralını kullanın

    public class XxxTest {
        @Rule
        public ExpectedException thrown = ExpectedException.none();
    
        @Test
        public void testFooThrowsIndexOutOfBoundsException() {
            thrown.expect(IndexOutOfBoundsException.class)
            //you can test the exception message like
            thrown.expectMessage("expected messages");
            foo.doStuff();
        }
    }
    
  • aynı zamanda junit 3 çerçevesinde yaygın olarak kullanılan klasik deneme / yakalama yöntemini de kullanabilirsiniz.

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        try {
            foo.doStuff();
            fail("expected exception was not occured.");
        } catch(IndexOutOfBoundsException e) {
            //if execution reaches here, 
            //it indicates this exception was occured.
            //so we need not handle it.
        }
    }
    
  • Son olarak, junit5.x için aşağıdaki gibi assertThrows kullanabilirsiniz

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
        assertEquals("expected messages", exception.getMessage());
    }
    
  • yani

    • 1. yöntem sadece testin istisna tipini istediğinizde kullanılır
    • Test istisnası mesajını daha fazla istediğinizde diğer üç yol kullanılır
    • Eğer 3'ü kullanırsanız 3'üncü tercih edilir.
    • Eğer 5'i seviyorsan, o zaman 4'ü sevmelisin.
  • daha fazla bilgi için okuyabilirsiniz bu belge ve junit5 kullanım kılavuzu detaylar için.


84
2017-08-05 08:05



Benim için bu en iyi cevaptır, tüm yolları çok net bir şekilde kapsar, teşekkürler! Kişisel olarak okunabilirlik için Junit4 ile 3. seçeneği kullanmaya devam ediyorum, boş catch bloğundan kaçınmak için ayrıca Throwable ve e - Nicolas Cornette
Kontrol edilmiş istisna beklemek için ExpectedException kullanmak mümkün mü? - miuser
Tüm bu, en iyi üç cevabın bir birikimidir. IMO, yeni bir şey eklemiyorsa bu cevap bile gönderilmemelidir. Sadece rep için (popüler bir soru) cevap. Oldukça işe yaramaz. - Paul Samsotha
Elbette, türetilmiş herhangi bir tür geçirebilirsiniz çünkü Trowable yönteme ExpectedException.expect. bakınız imza. @miuser - walsh


tl; Dr.

  • pre-JDK8: Eski güzelliği tavsiye edeceğim try-catch blok.

  • post-JDK8: Kullanmak için AssertJ veya özel lambdas kullanın olağanüstü davranışı.

4 ya da JUnit 5'ten bağımsız olarak.

uzun hikaye

Kendinize yazmak mümkündür kendin Yap  try-catch JUnit araçlarını bloke edin veya kullanın (@Test(expected = ...) ya da @Rule ExpectedException JUnit kural özelliği).

Ama bu şekilde çok zarif ve iyi karıştırmayın okunabilirlik bilge diğer araçlarla.

  1. try-catch bloğu test edilen davranışın etrafına yazmanız ve onaylama bloğundaki iddiayı yazmanız gerekir, bu iyi olabilir ama birçok kişi bu testin okuma akışını keser. Ayrıca bir Assert.fail sonunda try aksi takdirde test, iddiaların bir tarafını kaçırabilir; PMD, findbugs veya Sonar bu gibi konuları tespit edecektir.

  2. @Test(expected = ...) Daha az kod yazabildiğiniz için bu özellik ilginçtir ve daha sonra bu testin yazılması hata kodlama hatalarına daha az eğilimlidir. Fakat Bu yaklaşımın bazı alanları eksik.

    • Eğer test, istisna ya da mesaj gibi istisnai durumlar üzerinde ek kontroller gerektiriyorsa (iyi istisna mesajlar gerçekten önemlidir, kesin bir istisna tipine sahip olmak yeterli olmayabilir).
    • Ayrıca, yöntemin etrafında bir beklenti bulunduğundan, test edilen kodun nasıl yazıldığına bağlı olarak, test kodunun yanlış kısmı istisnayı atabilir ve yanlış pozitif teste neden olabilir. PMD, findbugs veya Sonar Bu kod hakkında ipuçları verecektir.

      @Test(expected = WantedException.class)
      public void call2_should_throw_a_WantedException__not_call1() {
          // init tested
          tested.call1(); // may throw a WantedException
      
          // call to be actually tested
          tested.call2(); // the call that is supposed to raise an exception
      }
      
  3. ExpectedException kural aynı zamanda önceki uyarıları düzeltmek için bir girişimdir, ama beklenti tarzı kullandığı için kullanmak biraz garip geliyor, EasyMock kullanıcılar bu stili çok iyi biliyor. Bazıları için uygun olabilir, ama eğer takip ederseniz Davranış Süreci Geliştirme (BDD) veya Yasaklamayı Yasakla (AAA) prensipleri ExpectedException kural yazım tarzına uymaz. Bunun yanı sıra, aynı @Test yolu, beklentiyi nereye koyacağınıza bağlı olarak.

    @Rule ExpectedException thrown = ExpectedException.none()
    
    @Test
    public void call2_should_throw_a_WantedException__not_call1() {
        // expectations
        thrown.expect(WantedException.class);
        thrown.expectMessage("boom");
    
        // init tested
        tested.call1(); // may throw a WantedException
    
        // call to be actually tested
        tested.call2(); // the call that is supposed to raise an exception
    }
    

    Test istisnasından önce beklenen istisna bile, testler BDD veya AAA'ya uyuyorsa okuma akışınızı bozar.

    Ayrıca bunu gör yorum Yap yazarı JUnit konulu ExpectedException.

Yani yukarıdaki bu seçenekler, tüm uyarıları yükler ve açıkça kodlayıcı hatalara karşı bağışık değildir.

  1. Umut verici görünen bu cevabı oluşturduktan sonra farkettiğim bir proje var. yakalama istisna.

    Projenin açıklamasının dediği gibi, bir kodlayıcının istisnayı yakalayan akıcı bir kod satırına yazmasına izin verir ve bu istisnayı daha sonraki iddialar için sunar. Ve herhangi bir onaylama kütüphanesini hamcrest veya AssertJ.

    Ana sayfadan alınan hızlı bir örnek:

    // given: an empty list
    List myList = new ArrayList();
    
    // when: we try to get the first element of the list
    when(myList).get(1);
    
    // then: we expect an IndexOutOfBoundsException
    then(caughtException())
            .isInstanceOf(IndexOutOfBoundsException.class)
            .hasMessage("Index: 1, Size: 0") 
            .hasNoCause();
    

    Gördüğünüz gibi, kod gerçekten basittir, belirli bir satırdaki istisnayı yakalarsınız. then API, AssertJ API'lerini kullanacak bir takma addır. assertThat(ex).hasNoCause()...). Bir noktada proje, Fest-Assert'e AssertJ'in atalarına dayanıyordu.. DÜZENLE: Görünüşe göre bu proje bir Java 8 Lambdas desteği sunuyor.

    Şu anda bu kütüphanede iki eksiklik var:

    • Bu yazı yazıldığı zaman, bu kütüphanenin, sahnenin arkasındaki test edilmiş nesnenin bir alayını yarattığı için, Mockito 1.x'e dayandığını söylemek dikkat çekicidir. Mockito hala güncellenmediğinden bu kütüphane son sınıflarla veya son yöntemlerle çalışamaz. Ve mevcut versiyonda mockito 2'ye dayanmış olsa bile, bunun küresel bir alaycı yapımcısını ilan etmesi gerekir (inline-mock-maker), istediğin bir şey olmayabilir, çünkü bu mockmaker'ın normal mockmaker'ın farklı sakıncaları vardır.

    • Başka bir test bağımlılığı gerektirir.

    Kütüphane lambdaları desteklediğinde bu sorunlar geçerli olmayacaktır, ancak işlevler AssertJ araç seti tarafından kopyalanacaktır.

    Catch-exception aracını kullanmak istemiyorsanız tüm bunları dikkate alarak, eski iyi bir şekilde try-catch En az JDK7'ye kadar blok. Ve JDK 8 kullanıcıları için AssertJ'i kullanmayı tercih edebilirsiniz, çünkü teklifler sadece istisnalar getirmekten daha fazla olabilir.

  2. JDK8 ile lambdalar test sahnesine girerler ve istisnai davranışları ortaya çıkarmanın ilginç bir yolu olduğunu kanıtlamışlardır. AssertJ, istisnai davranışlar sergilemek için güzel bir akıcı API sağlamak üzere güncellendi.

    Ve örnek bir test AssertJ :

    @Test
    public void test_exception_approach_1() {
        ...
        assertThatExceptionOfType(IOException.class)
                .isThrownBy(() -> someBadIOOperation())
                .withMessage("boom!"); 
    }
    
    @Test
    public void test_exception_approach_2() {
        ...
        assertThatThrownBy(() -> someBadIOOperation())
                .isInstanceOf(Exception.class)
                .hasMessageContaining("boom");
    }
    
    @Test
    public void test_exception_approach_3() {
        ...
        // when
        Throwable thrown = catchThrowable(() -> someBadIOOperation());
    
        // then
        assertThat(thrown).isInstanceOf(Exception.class)
                          .hasMessageContaining("boom");
    }
    
  3. JUnit 5'in neredeyse tamamlanmış bir yeniden yazımıyla, iddialar gelişmiş biraz, uygun istisna iddia etmek için kutunun dışında ilginç olarak kanıtlayabilirler. Ama gerçekten de iddiası API hala biraz zayıf, dışarıda hiçbir şey yok assertThrows.

    @Test
    @DisplayName("throws EmptyStackException when peeked")
    void throwsExceptionWhenPeeked() {
        Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
    
        Assertions.assertEquals("...", t.getMessage());
    }
    

    Fark ettiğin gibi assertEquals hala geri geliyor voidve bu nedenle AssertJ gibi zincirleme iddialarına izin vermez.

    Ayrıca isimle çatışmayı hatırlarsanız Matcher veya Assertile aynı çatışmayı karşılamaya hazır olun Assertions.

Bugün olduğu sonucuna varmak isterim (2017-03-03) AssertJKullanım kolaylığı, keşfedilebilir API, hızlı ilerleme hızı ve bir de facto Test bağımlılığı, test çerçevesinden (JUnit olsun ya da olmasın) bağımsız olarak JDK8 ile en iyi çözümdür; try-catch tıkanıklık hissetse bile engeller.

Bu cevap kopyalandı başka bir soru aynı görünüme sahip değil, aynı yazar.


58
2017-12-07 14:19



Org.junit.jupiter eklenmesi: junit-jupiter-engine: 5.0.0-RC2 bağımlılığı (halihazırda var olan cihaza ek olarak: cunit: 4.12) assertThrows kullanmak belki tercih edilen çözüm değildir, fakat Benim için sorunları. - anre
ExpectedException kuralını kullanmanın hayranıyım ama her zaman AAA ile kırıldığını beni rahatsız etti. Tüm farklı yaklaşımları tanımlamak için mükemmel bir makale yazdınız ve kesinlikle AssertJ'i denemem için beni teşvik ettiniz :-) Teşekkürler! - Pim Hazebroek
@PimHazebroek teşekkürler. AssertJ API oldukça zengindir. Benim düşünceme göre JUnit kutunun dışında ne önerdiğini daha iyi. - Brice


BDD Stil çözümü: JUnit 4 + Yakalama İstisnası + AssertJ

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    when(foo).doStuff();

    then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);

}

Kaynak kodu

Bağımlılıklar

eu.codearte.catch-exception:catch-exception:1.3.3

31
2017-11-15 19:17





Buna ne dersiniz: Çok genel bir istisnayı yakalayın, yakalama bloğundan çıkardığından emin olun, ardından istisna sınıfının olmasını beklediğiniz şey olduğunu belirtin. Eğer bu istisna a) istisna yanlış tipte ise (örneğin, boş bir işaretçiniz varsa) ve b) istisna atılmadıysa, bu iddia başarısız olacaktır.

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}

30
2017-10-01 07:03



JUnit 3'te yaptığınız buydu. Junit 4 bunu daha iyi yapar. - skaffman
Ayrıca, testin başarısız olduğu gün geldiğinde, test sonuçlarında Ex örneğinin ne tür olduğunu görmezsiniz. - jontejj


Bir AssertJ JUnit ile birlikte kullanılabilecek iddialar:

import static org.assertj.core.api.Assertions.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  Foo foo = new Foo();

  assertThatThrownBy(() -> foo.doStuff())
        .isInstanceOf(IndexOutOfBoundsException.class);
}

Den daha iyi @Test(expected=IndexOutOfBoundsException.class)çünkü testteki beklenen satırı garantilediğinden, istisnayı fırlattı ve mesaj gibi istisna hakkında daha fazla ayrıntı kontrol etmenizi sağlar:

assertThatThrownBy(() ->
       {
         throw new Exception("boom!");
       })
    .isInstanceOf(Exception.class)
    .hasMessageContaining("boom");

Maven / Gradle talimatları burada.


30
2018-03-05 11:07



en özlü yol ve kimse bunu takdir etmez, garip .. Sadece assertJ kütüphanesi ile ilgili bir problemim var. assertJ hakkında daha fazla bilgi: JUnit: Java 8 ve AssertJ 3.0.0 ile İstisnaları Test Etme ~ Codeleak.pl - ycomp
@ycomp Peki, çok eski bir soru için yeni bir cevaptır, bu yüzden skor farkı aldatıcıdır. - weston
Java 8 ve AssertJ kullanabiliyorsa muhtemelen en iyi çözüm budur! - Pierre Henry
@ycomp Bu isim çatışmasının tasarım gereği olabileceğinden şüpheleniyorum: AssertJ kütüphanesi bu nedenle JUnit'i asla kullanmamayı kesinlikle teşvik ediyor assertThat, her zaman AssertJ bir. Ayrıca, JUnit yöntemi yalnızca bir "normal" türünü döndürürken, AssertJ yöntemi bir AbstractAssert alt sınıf ... yukarıdaki yöntemlerin çekilmesine izin verir (veya teknik terimler bunun için ne olursa olsun ...). - mike rodent
@weston aslında tekniğini sadece AssertJ 2.0.0'da kullandım. Yeni sürüme geçmemize gerek yok, şüphesiz, ama bilmek isteyebilirsiniz. - mike rodent


Aynı sorunu çözmek için küçük bir proje kurdum: http://code.google.com/p/catch-exception/

Bu küçük yardımcıyı kullanarak yazarsın

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

Bu, JUnit 4.7'nin ExpectedException kuralından daha az ayrıntılıdır. Skaffman tarafından sağlanan çözümle karşılaştırıldığında, hangi kod satırında istisnayı beklediğinizi belirtebilirsiniz. Umarım bu yardımcı olur.


29
2017-10-28 09:26



Bunun gibi bir şey yapmayı düşündüm, ama sonuçta ExpectedException'ın gerçek gücünün yalnızca beklenen istisnayı belirtebildiğini değil, istisnanın beklenen özelliklerini veya beklenen mesajı gibi belirli özelliklerini de belirtebildiğini keşfettim. - Jason Thompson
bunu da yapabilirsiniz caughtException - Martin Trummer
Tahminimce bu çözümün alayla aynı sakıncaları var mı? Örneğin, foo olduğu final proxy yapamayacağınız için başarısız olacak foo? - Tom
Tom, doStuff () bir arabirimin parçasıysa, proxy yaklaşımı çalışır. Aksi takdirde bu yaklaşım başarısız olur, haklısınız. - rwitzel


Şimdi JUnit 5'in çıktığı, en iyi seçenek kullanmaktır Assertions.assertThrows() (görmek 5 numaralı kullanım kılavuzu).

İşte bir istisnanın doğrulandığını doğrulayan bir örnek ve Hakikat istisna mesajında ​​iddialarda bulunmak için:

public class FooTest {
  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    IndexOutOfBoundsException e = assertThrows(
        IndexOutOfBoundsException.class, foo::doStuff);

    assertThat(e).hasMessageThat().contains("woops!");
  }
}

Diğer cevaplardaki yaklaşımların avantajları şunlardır:

  1. JUnit'te yerleşik
  2. Eğer lambdadaki kod bir istisna alamazsa ve istisnai bir durum atarsa ​​bir stacktrace olursa, yararlı bir istisna mesajı alırsınız.
  3. Özlü
  4. Testlerinizin Düzenleme-Hareket Ettirme'yi takip etmesine izin verir
  5. İstisnai atmak için hangi kodu beklediğinizi tam olarak belirtebilirsiniz.
  6. Beklenen istisnayı listelemenize gerek yok. throws fıkra
  7. Yakalanan istisna hakkındaki iddiaları yapmak için seçtiğiniz savcılık çerçevesini kullanabilirsiniz.

Benzer bir yöntem eklenecektir org.junit Assert JUnit 4.13.


27
2017-10-01 16:42