java – 你如何断言在JUnit 4测试中引发了某种异常?

我如何通过惯用方式使用JUnit4来测试某些代码是否会抛出异常?

虽然我当然可以做这样的事情:

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

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

  assertTrue(thrown);
}

我记得有一个注释或一个Assert.xyz或者其他一些远远不够灵活的东西,而且在这种情况下JUnit的精神远不止于此


JUnit 4支持这一点:

@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);
}

参考:https//junit.org/junit4/faq.html#atests_7


 

编辑现在JUnit5已经发布,最好的选择是使用Assertions.assertThrows()(请参阅我的其他答案)。

如果您尚未迁移到JUnit 5,但可以使用JUnit 4.7,则可以使用ExpectedExceptionRule:

public class FooTest {
  @Rule
  public final ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    foo.doStuff();
  }
}

这比之前抛出@Test(expected=IndexOutOfBoundsException.class)的测试会失败要好得多IndexOutOfBoundsExceptionfoo.doStuff()

请参见本文的详细信息


如前所述,在JUnit中处理异常的方法有很多。但是对于Java 8,还有另外一个:使用Lambda表达式。使用Lambda表达式,我们可以实现这样的语法:

@Test
public void verifiesTypeAndMessage() {
    assertThrown(new DummyService()::someMethod)
            .isInstanceOf(RuntimeException.class)
            .hasMessage("Runtime exception occurred")
            .hasMessageStartingWith("Runtime")
            .hasMessageEndingWith("occurred")
            .hasMessageContaining("exception")
            .hasNoCause();
}

assertThrown接受一个函数接口,它的实例可以用lambda表达式,方法引用或构造函数引用来创建。assertThrown接受该接口将期望并准备好处理异常。

这是相对简单但功能强大的技术。

看看这个博客文章描述这种技术:http : //blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

源代码可以在这里找到:https//github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

披露:我是博客和项目的作者。

添加评论

友情链接:蝴蝶教程