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

时间:2016-10-26 17:19:17

标签: java junit junit5 junit-jupiter

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

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

10 个答案:

答案 0 :(得分:173)

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

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

答案 1 :(得分:69)

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

  

public static< T延伸Throwable> T assertThrows(Class< T> expectedType,                                                      可执行的可执行文件)

     

断言执行提供的可执行文件会抛出expectedType的异常并返回异常。

     

如果没有抛出异常,或者抛出了不同类型的异常,则此方法将失败。

     

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

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

该方法将使用Executable中的功能界面org.junit.jupiter.api

参考:

答案 2 :(得分:22)

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

public class two {

  private void anotherMethod() throws Exception {
    synchronized(one.locker) {
      for (int i = 0; i < 10; i++) {
        Thread.sleep(500);
        one.locker.notifyAll();
      }
    }
  }

  public static void main(String args[]) {
    try { new two().anotherMethod(); }
    catch (Exception e) { e.printStackTrace(); }
  }
}

答案 3 :(得分:16)

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

答案 4 :(得分:6)

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

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

在包含空get()的可选项上调用ArrayList会抛出NoSuchElementExceptionassertThrows声明预期的异常并提供lambda供应商(不接受任何参数并返回值)。

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

答案 5 :(得分:5)

您可以使用#ifndef SOCKET_H #define SOCKET_H #include <QObject> #include <QDebug> #include <QTcpServer> #include <QTcpSocket> class QTextBrowser; class Socket : public QObject { Q_OBJECT public: explicit Socket(QObject *parent = 0); void setWindow(Window *w); signals: public slots: void newConnection(); private: QTcpServer *server; Window *window; }; #endif // SOCKET_H 。我的示例来自文档http://junit.org/junit5/docs/current/user-guide/

assertThrows()

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

slarge = large.stack()
slarge.size + slarge.index.size

2000000

答案 8 :(得分:0)

这是一种简单的方法。

@Test
void exceptionTest() {

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

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

}

它仅在引发您期望的异常时成功。

答案 9 :(得分:-3)

有3种方法可以在Junit中声明某个异常。让我们为其编写单元测试用例。

1。尝试捕捉习语 该惯用语是最受欢迎的惯用语之一,因为它已在JUnit 3中使用。这种方法是一种常见模式。如果没有引发异常并且在catch子句中验证了异常本身,则测试将失败。

@Test
public void convertIntoUpperCase_withInvalidInput_tryCatchIdiom() {
    try {
        exceptionHandling.convertIntoUpperCase("");
        fail("It should throw IllegalArgumentException");
    } catch (IllegalArgumentException e) {
        Assertions.assertThat(e)
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("Empty value is passed.");
    }
}

2。 @Test预期注释 在这种方法中,我们在@Test中指定预期的异常,如下所示 @Test(expected = IllegalArgumentException.class)

未引发异常时,您将收到以下消息:java.lang.AssertionError:预期的异常:java.lang.IllegalArgumentException

使用这种方法时,您需要小心。有时很容易想到一般的Exception,RuntimeException甚至Throwable。这被认为是一种不好的做法,因为您的代码可能会在实际所期望的其他地方引发异常,并且测试仍然可以通过!

此方法的缺点之一是您无法断言异常消息。

@Test(expected = IllegalArgumentException.class)
public void convertIntoUpperCase_withInvalidInput_testExpected() {
    exceptionHandling.convertIntoUpperCase("");
}

3。 Junit @Rule 可以使用ExceptedException规则创建相同的示例。规则必须是标有@Rule批注的公共字段。

    @Test
    public void convertIntoUpperCase_withInvalidInput_ExpectedExceptionRule() {
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("Empty value is passed.");
        exceptionHandling.convertIntoUpperCase("");
    }

我发现上面的代码更具可读性,因此我更喜欢使用这种方法。

当未引发异常时,您将收到以下消息:java.lang.AssertionError:预期引发的测试(java.lang.IllegalArgumentException的实例和带有“空值已传递。”消息的异常)。很好。

但并非所有例外都可以通过上述方法进行检查。有时我只需要检查引发的异常的类型,然后使用@Test批注即可。