如何使用JUnit来测试某些代码是否抛出异常?

我当然可以这样做:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

我记得,对于这类情况,有一个注释或Assert.xyz之类的东西远没有JUnit那么笨拙,更符合JUnit的精神。


当前回答

使用Java 8,您可以创建一个方法,将要检查的代码和预期异常作为参数:

private void expectException(Runnable r, Class<?> clazz) { 
    try {
      r.run();
      fail("Expected: " + clazz.getSimpleName() + " but not thrown");
    } catch (Exception e) {
      if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
    }
  }

然后在测试中:

expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);

优点:

不依赖任何库本地化检查-更精确,如果需要,允许在一个测试中有多个这样的断言易于使用

其他回答

JUnit框架具有assertThrows()方法:

ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
    calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());

对于JUnit 5,它位于org.unit.jupiter.api.Assertions类中;对于JUnit 4.13,它位于org.JUnit.Assert类中;对于JUnit4的早期版本:只需将org.JUnit.jupiter:junitjupiterapi上的引用添加到项目中,就可以从JUnit5获得非常好的工作版本。

这取决于JUnit版本和使用的断言库。

JUnit5和4.13见答案如果您使用AssertJ或google truth,请参阅答案

JUnit<=4.12的原始答案是:

    @Test(expected = IndexOutOfBoundsException.class)
    public void testIndexOutOfBoundsException() {

        ArrayList emptyList = new ArrayList();
        Object o = emptyList.get(0);

    }

尽管答案对于JUnit<=4.12有更多选项。

参考:

JUnit测试常见问题解答

我建议库assertj核心处理junit测试中的异常

在java 8中,如下所示:

//given

//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));

//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);

JUnit内置了对此的支持,并带有“expected”属性。

try {
    my method();
    fail( "This method must thrwo" );
} catch (Exception ex) {
    assertThat(ex.getMessage()).isEqual(myErrormsg);
}