Junit 5:如何断言一个例外?

发布于 2025-01-28 06:02:19 字数 118 浏览 7 评论 0原文

是否有更好的方法可以断言一种方法在Junit 5中引发了例外?

当前,我必须使用@rule才能验证我的测试会引发异常,但是对于我期望多种方法在测试中引发异常的情况下,这不起作用。

Is there a better way to assert that a method throws an exception in JUnit 5?

Currently, I have to use a @Rule in order to verify that my test throws an exception, but this doesn't work for the cases where I expect multiple methods to throw exceptions in my test.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

夏有森光若流苏 2025-02-04 06:02:19

您可以使用 assertthrows() ,它允许您在同一测试中测试多个异常。在Java 8中支持Lambdas的支持下,这是测试Junit例外的规范方法。

per 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"));
}

You can use assertThrows(), which allows you to test multiple exceptions within the same test. With support for lambdas in Java 8, this is the canonical way to test for exceptions in JUnit.

Per the 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"));
}
白龙吟 2025-02-04 06:02:19

在Java 8和Junit 5(木星)中,我们可以主张例外,如下所示。
使用org.junit.jupiter.api.assertions.assertthrows

公共静态< t可以扩展可投掷> t essertthrows(class< t> endiveptype,
可执行执行)

断言,所提供的可执行文件的执行会抛出ExpectyType的例外并返回例外。

如果抛出了任何例外,或者抛出了其他类型的例外,则此方法将失败。

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

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

该方法将在org.junit.jupiter.api中使用功能界面可执行

请参阅:

In Java 8 and JUnit 5 (Jupiter) we can assert for exceptions as follows.
Using org.junit.jupiter.api.Assertions.assertThrows

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

Asserts that execution of the supplied executable throws an exception of the expectedType and returns the exception.

If no exception is thrown, or if an exception of a different type is thrown, this method will fail.

If you do not want to perform additional checks on the exception instance, simply ignore the return value.

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

That approach will use the Functional Interface Executable in org.junit.jupiter.api.

Refer :

野心澎湃 2025-02-04 06:02:19

tl; dr:如果您在Junit 5.8.0+版本上,则应使用AssertThrowSactly()而不是assertthrows()匹配确切的异常类型。

assertThrowsExactly(FileNotFoundException.class, () -> service.blah());

您可以使用assertthrows(),但是使用assertthrows即使抛出的例外是儿童类型,您的断言也会通过。

这是因为,junit 5通过调用class.isintance(..)class.isinstance(..)也将返回true,即使投掷异常是儿童类型。

解决方法是在课堂上断言:

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

TL;DR: If you are on JUnit 5.8.0+ version, you should use assertThrowsExactly() instead of assertThrows() to match the exact exception type.

assertThrowsExactly(FileNotFoundException.class, () -> service.blah());

You can use assertThrows(), But with assertThrows your assertion will pass even if the thrown exception is of child type.

This is because, JUnit 5 checks exception type by calling Class.isIntance(..), Class.isInstance(..) will return true even if the thrown exception is of a child type.

The workaround for this is to assert on Class:

Throwable throwable =  assertThrows(Throwable.class, () -> {
    service.readFile("sampleFile.txt");
});
assertEquals(FileNotFoundException.class, throwable.getClass());
嘦怹 2025-02-04 06:02:19

他们在Junit 5中更改了它(预期:InvealArgumentException,实际:调用方法),并且代码看起来像这样:

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

They've changed it in JUnit 5 (expected: InvalidArgumentException, actual: invoked method) and code looks like this one:

@Test
public void wrongInput() {
    Throwable exception = assertThrows(InvalidArgumentException.class,
            ()->{objectName.yourMethod("WRONG");} );
}
梦行七里 2025-02-04 06:02:19

现在,junit5提供了一种断言例外的方法,

您可以同时测试一般异常和定制异常

一个一般的例子:

greengegeneralexception.java

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

greengeneralexceptiontest.java.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在这里:断言异常代码样本

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

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

Now Junit5 provides a way to assert the exceptions

You can test both general exceptions and customized exceptions

A general exception scenario:

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

You can find a sample to test CustomException here : assert exception code sample

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());
}
薯片软お妹 2025-02-04 06:02:19

您可以使用assertthrows()。我的示例取自docs http://junit.org/junit.org/junit5/junit5/junit5/docs/current5/current5 /用户指导/

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

You can use assertThrows(). My example is taken from the docs 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());
}
寄居者 2025-02-04 06:02:19

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

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

呼叫get()包含一个空arrayList的可选将抛出nosuchelementExceptionAssertthrows声明了预期的异常并提供了lambda供应商(不需要参数并返回值)。

感谢@prime的回答,我希望得到详细说明。

I think this is an even simpler example

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

Calling get() on an optional containing an empty ArrayList will throw a NoSuchElementException. assertThrows declares the expected exception and provides a lambda supplier (takes no arguments and returns a value).

Thanks to @prime for his answer which I hopefully elaborated on.

七月上 2025-02-04 06:02:19

一个更简单的衬里。使用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()
}

An even simpler one liner. No lambda expressions or curly braces required for this example using Java 8 and JUnit 5

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()
}
软甜啾 2025-02-04 06:02:19

我的解决方案:

    protected <T extends Throwable> void assertExpectedException(ThrowingRunnable methodExpectedToFail, Class<T> expectedThrowableClass,
        String expectedMessage) {
    T exception = assertThrows(expectedThrowableClass, methodExpectedToFail);
    assertEquals(expectedMessage, exception.getMessage());
}

您可以这样称呼:

    assertExpectedException(() -> {
        carService.findById(id);
    }, IllegalArgumentException.class, "invalid id");

My solution:

    protected <T extends Throwable> void assertExpectedException(ThrowingRunnable methodExpectedToFail, Class<T> expectedThrowableClass,
        String expectedMessage) {
    T exception = assertThrows(expectedThrowableClass, methodExpectedToFail);
    assertEquals(expectedMessage, exception.getMessage());
}

And you can call it like this:

    assertExpectedException(() -> {
        carService.findById(id);
    }, IllegalArgumentException.class, "invalid id");
寄与心 2025-02-04 06:02:19

这是我在测试时要做的,以确保已抛出异常

//when
final var tripConsumer = new BusTripConsumer(inputStream);
final Executable executable = () -> tripConsumer.deserialiseTripData();

//then
assertThrows(IllegalArgumentException.class, executable);

This is what I do when testing to make sure an exception has been thrown

//when
final var tripConsumer = new BusTripConsumer(inputStream);
final Executable executable = () -> tripConsumer.deserialiseTripData();

//then
assertThrows(IllegalArgumentException.class, executable);
萤火眠眠 2025-02-04 06:02:19

实际上,我认为该特定示例的文档中存在错误。预期的方法是

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

Actually I think there is a error in the documentation for this particular example. The method that is intended is expectThrows

public static void assertThrows(
public static <T extends Throwable> T expectThrows(
于我来说 2025-02-04 06:02:19

user1075613

您可能有兴趣检查assertj是否比Junit5

更灵活。

,并且还会生成拟合错误消息。 示例

  assertThatThrownBy(() -> someMethod(param1, param2))
        .isInstanceOf(NullPointerException.class);

As mentioned in the comment by user1075613:

you might be interested to check AssertJ for checking exceptions at it is more flexible than JUnit5

and it also generates fitting error message. Example:

  assertThatThrownBy(() -> someMethod(param1, param2))
        .isInstanceOf(NullPointerException.class);
十雾 2025-02-04 06:02:19

这是一种简单的方法。

@Test
void exceptionTest() {

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

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

}

它只有在您期望抛出的例外情况下才能成功。

Here is an easy way.

@Test
void exceptionTest() {

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

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

}

It only succeeds when the Exception you expect is thrown.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文