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

我当然可以这样做:

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

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

  assertTrue(thrown);
}

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


当前回答

我在Mkyong博客中找到了Junit 4最灵活、最优雅的答案。它具有使用@Rule注释的try/catch的灵活性。我喜欢这种方法,因为您可以读取自定义异常的特定属性。

package com.mkyong;

import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;

public class Exception3Test {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testNameNotFoundException() throws NameNotFoundException {

        //test specific type of exception
        thrown.expect(NameNotFoundException.class);

        //test message
        thrown.expectMessage(is("Name is empty!"));

        //test detail
        thrown.expect(hasProperty("errCode"));  //make sure getters n setters are defined.
        thrown.expect(hasProperty("errCode", is(666)));

        CustomerService cust = new CustomerService();
        cust.findByName("");

    }

}

其他回答

BDD风格解决方案:JUnit 4+Catch异常+AssertJ

import static com.googlecode.catchexception.apis.BDDCatchException.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    when(() -> foo.doStuff());

    then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);

}

依赖关系

eu.codearte.catch-exception:catch-exception:2.0
try {
    my method();
    fail( "This method must thrwo" );
} catch (Exception ex) {
    assertThat(ex.getMessage()).isEqual(myErrormsg);
}

这样如何:捕获一个非常普通的异常,确保它从catch块中取出,然后断言该异常的类是您期望的。如果a)异常类型错误(例如,如果您使用了空指针),并且b)该异常从未被抛出,则该断言将失败。

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}

在junit中,有四种方法可以测试异常。

六月5.x

对于junit5.x,可以使用assertThrows,如下所示@测试public void testFooThrowsIndexOutOfBoundsException(){抛出异常=assertThrows(IndexOutOfBoundsException.class,()->foo.doStuff());assertEquals(“预期消息”,exception.getMessage());}

六月4.x

对于junit4.x,使用测试注释的可选“expected”属性@测试(应为IndexOutOfBoundsException.class)public void testFooThrowsIndexOutOfBoundsException(){foo.doStuff();}对于junit4.x,请使用ExpectedException规则公共类XxxTest{@规则引发了public ExpectedException=ExpectedException.none();@测试public void testFooThrowsIndexOutOfBoundsException(){引发.预期(IndexOutOfBoundsException.class)//您可以像这样测试异常消息抛出.expectMessage(“预期消息”);foo.doStuff();}}您还可以使用junit3框架下广泛使用的经典try/catch方法@测试public void testFooThrowsIndexOutOfBoundsException(){尝试{foo.doStuff();fail(“未发生预期的异常。”);}catch(IndexOutOfBoundsException e){//如果执行到达这里,//它表示发生了此异常。//所以我们不需要处理它。}}所以如果你喜欢junit 5,那么你应该喜欢第一个当您只想测试异常类型时,使用第二种方法当需要进一步测试异常消息时,使用前两个和后两个如果您使用junit 3,则首选第四个有关详细信息,您可以阅读本文档和junit5用户指南。

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