JUnit 5:抛出如何断言异常?

ste*_*ble 162 java junit junit5 junit-jupiter

有没有更好的方法断言方法在JUnit 5中抛出异常?

目前,我必须使用@Rule来验证我的测试是否会引发异常,但这对于我希望多个方法在我的测试中抛出异常的情况不起作用.

ste*_*ble 241

您可以使用assertThrows(),它允许您在同一测试中测试多个异常.在Java 8中支持lambdas,这是在JUnit中测试异常的规范方法.

根据JUnit文档:

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"));
}
Run Code Online (Sandbox Code Playgroud)

  • 从一个老派"我不太了解Junit5,可能还不够Java8"......这看起来很奇怪.你介意补充一些解释吗?比如"那里的哪个部分是实际的'生产代码'正在测试......那应该扔掉"? (10认同)
  • 从版本5.0.0-M4**到expectThrows**已不再可用.只允许**assertThrows**.请参阅https://github.com/junit-team/junit5/blob/master/documentation/src/docs/asciidoc/release-notes-5.0.0-M4.adoc:'删除弃用的Assertions.expectThrows()方法of Assertions.assertThrows()' (5认同)
  • 木星是如此蹩脚,迫使我们以这种方式断言信息:-/ (5认同)
  • `() ->` _points_ 到一个接受零参数的 lambda 表达式。因此,预期抛出异常的“生产代码”位于_指向_的代码块中(即大括号内的`throw new...`语句)。 (2认同)
  • 通常,lambda 表达式会与被测对象 (SUT) 进行交互。换句话说,像上面那样直接抛出异常只是为了演示目的。 (2认同)

pri*_*ime 79

在Java 8和JUnit 5(Jupiter)中,我们可以声明异常,如下所示.运用org.junit.jupiter.api.Assertions.assertThrows

public static <T extends Throwable> T assertThrows(Class <T> expectedType,Executable executable)

断言所提供的可执行文件的执行会引发expectedType的异常并返回异常.

如果未引发异常,或者抛出了其他类型的异常,则此方法将失败.

如果您不想对异常实例执行其他检查,只需忽略返回值.

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

这一方法将使用功能接口Executableorg.junit.jupiter.api.

参考:

  • 凭借这个登上顶峰!这是迄今为止 JUnit 5 最新的最佳答案。此外,如果 Lambda 只有一行:`assertThrows(NoSuchElementException.class, myLinkedList::getFirst),IntelliJ 会进一步压缩 lambda ;` (2认同)

jst*_*tar 25

他们在JUnit 5中更改了它(预期:InvalidArgumentException,actual:invoked method),代码如下所示:

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


Anu*_*dda 19

现在,Junit5提供了一种断言异常的方法

您可以测试一般例外和自定义例外

一般异常情况:

ExpectGeneralException.java

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

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());
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到测试CustomException的示例:断言异常代码示例

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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());
}
Run Code Online (Sandbox Code Playgroud)


Gov*_*are 9

您可以使用assertThrows(), 但是assertThrows即使抛出的异常是子类型的,您的断言也会通过。

这是因为,JUnit 5 通过调用来检查异常类型Class.isIntance(..)Class.isInstance(..)即使抛出的异常属于子类型,也会返回 true。

解决方法是在 Class 上断言:

Throwable throwable =  assertThrows(Throwable.class, () -> {
    service.readFile("sampleFile.txt");
});
assertEquals(FileNotFoundException.class, throwable.getClass());
Run Code Online (Sandbox Code Playgroud)


Wil*_*eys 7

你可以用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());
}
Run Code Online (Sandbox Code Playgroud)


rny*_*nja 7

更简单的单衬。使用 Java 8 和 JUnit 5 的此示例不需要 lambda 表达式或大括号

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()
}
Run Code Online (Sandbox Code Playgroud)


Jes*_*oyd 6

我认为这是一个更简单的例子

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

调用get()包含空的可选项ArrayList将抛出一个NoSuchElementException. assertThrows声明预期的异常并提供lambda供应商(不接受任何参数并返回值).

感谢@prime的回答,我希望能够详细阐述.