JUnit 5: Bir istisna atılır nasıl iddia edilir?


215

JUnit 5'te bir yöntemin bir istisna attığını iddia etmenin daha iyi bir yolu var mı?

Şu anda, testimin bir istisna attığını doğrulamak için bir @ Kural kullanmalıyım, ancak bu, testime istisnalar atmak için birden fazla yöntem beklediğim durumlarda işe yaramaz.


1
İstisnaları kontrol etmek için AssertJ'yi JUnit5'ten daha esnek olup olmadığını kontrol etmek isteyebilirsiniz
user1075613

Yanıtlar:


324

assertThrows()Aynı test içinde birden fazla istisnayı test etmenizi sağlayan kullanabilirsiniz . Java 8'deki lambdas desteğiyle, bu, JUnit'teki istisnaları test etmenin kanonik yoludur.

Başına JUnit docs :

import static org.junit.jupiter.api.Assertions.assertThrows;

@Test
void exceptionTesting() {
    MyException thrown = assertThrows(
           MyException.class,
           () -> myObject.doThing(),
           "Expected doThing() to throw, but it didn't"
    );

    assertTrue(thrown.getMessage().contains("Stuff"));
}

11
Eski bir okuldan "Junit5 hakkında fazla bir şey bilmiyorum ve muhtemelen Java8 hakkında yeterli değil" ... bu oldukça tuhaf görünüyor. Daha fazla açıklama eklemek ister misiniz; "test edilecek asıl 'üretim kodu' hangi kısımda ... atması gereken" gibi?
GhostCat

1
() -> noktaları sıfır bağımsız değişken kabul eden bir lambda ifadesi için. Bu nedenle, istisnayı atması beklenen "üretim kodu", işaret edilen kod bloğundadır (yani, throw new...süslü parantez içindeki ifade).
Sam Brannen

1
Tipik olarak lambda ifadesi test edilen hasta (SUT) ile etkileşime girer. Başka bir deyişle, doğrudan yukarıdaki gibi bir istisna atmak sadece tanıtım amaçlıdır.
Sam Brannen

1
WaitThrows kullanımdan kaldırıldı. Dokümanlar şimdi bunun yerine assertThrows () yöntemini kullandığını söylüyor.
depsypher

5
5.0.0-M4 sürümü itibariyle waitThrows artık mevcut değil. Sadece assertThrows'a izin verilir. Bkz github.com/junit-team/junit5/blob/master/documentation/src/docs/... : 'kaldırıldı kaldırılmış Assertions.expectThrows () yöntemini Assertions.assertThrows lehine ()'
gil.fernandes

91

Java 8 ve JUnit 5'te (Jüpiter) istisnalar için aşağıdaki gibi iddiada bulunabiliriz. kullanmaorg.junit.jupiter.api.Assertions.assertThrows

public static <T Genişletilebilir> T assertThrows'u (Sınıf <T> beklenen Tür, Yürütülebilir yürütülebilir)

Sağlanan yürütülebilir dosyanın yürütülmesinin beklenen türden bir istisna attığını ve istisnayı döndürdüğünü iddia eder.

Herhangi bir istisna atılmazsa veya farklı türde bir istisna atılırsa, bu yöntem başarısız olur.

İstisna örneğinde ek denetimler yapmak istemiyorsanız, dönüş değerini yok saymanız yeterlidir.

@Test
public void itShouldThrowNullPointerExceptionWhenBlahBlah() {
    assertThrows(NullPointerException.class,
            ()->{
            //do whatever you want to do here
            //ex : objectName.thisMethodShoulThrowNullPointerExceptionForNullParameter(null);
            });
}

Bu yaklaşım, ' Executabledaki İşlevsel Arayüzü kullanacaktır org.junit.jupiter.api.

Bakınız:


1
Bununla zirveye! Bu, JUnit 5 ile bugüne kadarki en iyi cevaptır.Ayrıca, IntelliJ, Lambda'ya sadece bir satır varsa assertThrows(NoSuchElementException.class, myLinkedList::getFirst);
lambda'yı

26

JUnit 5'te değiştirdiler (beklenen: InvalidArgumentException, actual: invoked method) ve kod şuna benzer:

@Test
public void wrongInput() {
    Throwable exception = assertThrows(InvalidArgumentException.class,
            ()->{objectName.yourMethod("WRONG");} );
}

21

Artık Junit5 istisnaları iddia etmenin bir yolunu sunuyor

Hem genel istisnaları hem de özelleştirilmiş istisnaları test edebilirsiniz

Genel bir istisna senaryosu:

ExpectGeneralException.java

public void validateParameters(Integer param ) {
    if (param == null) {
        throw new NullPointerException("Null parameters are not allowed");
    }
}

ExpectGeneralExceptionTest.java

@Test
@DisplayName("Test assert NullPointerException")
void testGeneralException(TestInfo testInfo) {
    final ExpectGeneralException generalEx = new ExpectGeneralException();

     NullPointerException exception = assertThrows(NullPointerException.class, () -> {
            generalEx.validateParameters(null);
        });
    assertEquals("Null parameters are not allowed", exception.getMessage());
}

CustomException'ı test etmek için bir örnek burada bulabilirsiniz: assert istisna kodu örneği

ExpectCustomException.java

public String constructErrorMessage(String... args) throws InvalidParameterCountException {
    if(args.length!=3) {
        throw new InvalidParameterCountException("Invalid parametercount: expected=3, passed="+args.length);
    }else {
        String message = "";
        for(String arg: args) {
            message += arg;
        }
        return message;
    }
}

ExpectCustomExceptionTest.java

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

1
JUnit'in yerleşik ve özel istisnaları işleme biçimi arasında bir fark yoktur.
raindev

9

Bence bu çok daha basit bir örnek

List<String> emptyList = new ArrayList<>();
Optional<String> opt2 = emptyList.stream().findFirst();
assertThrows(NoSuchElementException.class, () -> opt2.get());

get()Boş içeren bir isteğe bağlı çağrı yapmak ArrayLista NoSuchElementException. assertThrowsbeklenen istisnayı bildirir ve bir lambda tedarikçisi sağlar (argüman almaz ve bir değer döndürür).

Umarım üzerinde durduğum cevap için @ prime'a teşekkürler.


1
yöntem assertThrowsatılan istisnayı döndürür. Böylece NoSuchElementException e = assertThrows(NoSuchElementException.class, () -> opt2.get());aşağıdaki gibi yapabilirsin İstediğiniz istisna nesnesiyle ilgili her türlü iddiayı yapabilirsiniz.
Kaptan Adam

8

Kullanabilirsiniz assertThrows(). Örneğim http://junit.org/junit5/docs/current/user-guide/ dokümanlarından alınmıştır.

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

....

@Test
void exceptionTesting() {
    Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
        throw new IllegalArgumentException("a message");
    });
    assertEquals("a message", exception.getMessage());
}

2

Daha da basit bir astar. Java 8 ve JUnit 5 kullanan bu örnek için lambda ifadesi veya süslü ayraç gerekmez

import static org.junit.jupiter.api.Assertions.assertThrows;

@Test
void exceptionTesting() {

    assertThrows(MyException.class, myStackObject::doStackAction, "custom message if assertion fails..."); 

// note, no parenthesis on doStackAction ex ::pop NOT ::pop()
}

1

Aslında bu örnek için belgelerde bir hata olduğunu düşünüyorum. Amaçlanan yöntem beklemektedir

public static void assertThrows(
public static <T extends Throwable> T expectThrows(

3
"Onaylanmamış Assertions.expectThrows () yöntemi, Assertions.assertThrows () lehine kaldırıldı."
Martin Schröder

5 Haziran için org.junit.jupiter.api.Assertions değil org.testng.Assert olduğundan emin olun. Projemiz hem Junit hem de TestNG'yi içeriyor ve assertExpects olarak değiştirene kadar assertThrows geçersiz hata döndürüyor. Org.testng.Assert kullandığım ortaya çıktı.
barryku

-5

İşte kolay bir yol.

@Test
void exceptionTest() {

   try{
        model.someMethod("invalidInput");
        fail("Exception Expected!");
   }
   catch(SpecificException e){

        assertTrue(true);
   }
   catch(Exception e){
        fail("wrong exception thrown");
   }

}

Sadece beklediğiniz İstisna atıldığında başarılı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.