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

我当然可以这样做:

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

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

  assertTrue(thrown);
}

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


当前回答

为了解决同样的问题,我设立了一个小项目:http://code.google.com/p/catch-exception/

使用这个小助手,您可以编写

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

这比JUnit 4.7的ExpectedException规则更详细。与skaffman提供的解决方案相比,您可以指定期望在哪行代码中出现异常。我希望这有帮助。

其他回答

使用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);

优点:

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

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

我在这里尝试了许多方法,但它们要么很复杂,要么不太符合我的要求。事实上,可以非常简单地编写一个助手方法:

public class ExceptionAssertions {
    public static void assertException(BlastContainer blastContainer ) {
        boolean caughtException = false;
        try {
            blastContainer.test();
        } catch( Exception e ) {
            caughtException = true;
        }
        if( !caughtException ) {
            throw new AssertionFailedError("exception expected to be thrown, but was not");
        }
    }
    public static interface BlastContainer {
        public void test() throws Exception;
    }
}

这样使用:

assertException(new BlastContainer() {
    @Override
    public void test() throws Exception {
        doSomethingThatShouldExceptHere();
    }
});

零依赖:无需mockito,无需powermock;在期末考试中表现很好。

为了解决同样的问题,我设立了一个小项目:http://code.google.com/p/catch-exception/

使用这个小助手,您可以编写

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

这比JUnit 4.7的ExpectedException规则更详细。与skaffman提供的解决方案相比,您可以指定期望在哪行代码中出现异常。我希望这有帮助。

JUnit 5解决方案

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

@Test
void testFooThrowsIndexOutOfBoundsException() {    
  IndexOutOfBoundsException exception = expectThrows(IndexOutOfBoundsException.class, foo::doStuff);
     
  assertEquals("some message", exception.getMessage());
}

关于JUnit 5的更多信息http://junit.org/junit5/docs/current/user-guide/#writing-测试断言