Подтвердить что ты не робот

JUnit 5: Как утвердить исключение?

Есть ли лучший способ утверждать, что метод генерирует исключение в JUnit 5?

В настоящее время я должен использовать @Rule для проверки того, что мой тест выдает исключение, но это не работает для случаев, когда я ожидаю, что несколько методов будут генерировать исключения в моем тесте.

4b9b3361

Ответ 1

Вы можете использовать assertThrows(), который позволяет тестировать несколько исключений в одном тесте. С поддержкой лямбд в Java 8 это, вероятно, станет каноническим способом проверки исключений в JUnit.

Согласно документам JUnit:

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

...

@Test
void exceptionTesting() {
    Executable closureContainingCodeToTest =
      // This represents production code that is expected to throw
      () -> throw new IllegalArgumentException("a message");

    assertThrows(IllegalArgumentException.class,
      closureContainingCodeToTest,
      "We expect the code under test to throw, but it didn't");
}

Ответ 2

В Java 8 и JUnit 5 (Юпитер) мы можем утверждать об исключениях следующим образом. Использование org.junit.jupiter.api.Assertions.assertThrows

public static <T extends Throwable> T assertThrows (класс <T> Ожидаемый тип, исполняемый файл)

Утверждает, что выполнение предоставленного исполняемого файла вызывает исключение ожидаемого типа и возвращает исключение.

Если не сгенерировано исключение или если сгенерировано исключение другого типа, этот метод завершится ошибкой.

Если вы не хотите выполнять дополнительные проверки экземпляра исключения, просто проигнорируйте возвращаемое значение.

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

Этот подход будет использовать Executable org.junit.jupiter.api функционального интерфейса в org.junit.jupiter.api.

См.:

Ответ 3

Они изменили его в JUnit 5 (ожидается: InvalidArgumentException, actual: invoked method), и код выглядит следующим образом:

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

Ответ 4

Теперь Junit5 предоставляет возможность утверждать исключения

Вы можете протестировать как общие исключения, так и настраиваемые исключения

Общий сценарий исключения:

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 здесь: пример кода исключения assert

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());
}

Ответ 5

Я думаю, что это еще более простой пример

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

Вызов get() для необязательного NoSuchElementException содержащего пустой ArrayList вызовет NoSuchElementException. assertThrows объявляет ожидаемое исключение и предоставляет лямбда-поставщика (не принимает аргументов и возвращает значение).

Спасибо @prime за его ответ, который я надеюсь развить.

Ответ 6

Вы можете использовать assertThrows(). Мой пример взят из документов http://junit.org/junit5/docs/current/user-guide/

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());
}

Ответ 7

На самом деле, я думаю, что ошибка в документации для этого конкретного примера. Предполагаемый метод - ожидатьThrows

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

Ответ 8

Вот простой способ.

@Test
void exceptionTest() {

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

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

}

Успешно, только когда вы ожидаете исключения.