我们如何断言在JUnit 4测试中引发了某种异常?
时间:2020-03-06 14:57:50 来源:igfitidea点击:
如何惯用JUnit4来测试某些代码引发异常?
虽然我当然可以做这样的事情:
@Test public void testFooThrowsIndexOutOfBoundsException() { boolean thrown = false; try { foo.doStuff(); } catch (IndexOutOfBoundsException e) { thrown = true; } assertTrue(thrown); }
我记得在这种情况下,有一个批注或者一个Assert.xyz或者一些不那么杂乱无章的东西,更像是JUnit的精髓。
解决方案
怎么做:捕获一个非常通用的异常,确保它使它脱离catch块,然后断言该异常的类就是我们期望的异常。如果a)异常的类型错误(例如,如果我们改为使用Null指针),并且b)从未引发异常,则该断言将失败。
public void testFooThrowsIndexOutOfBoundsException() { Throwable e = null; try { foo.doStuff(); } catch (Throwable ex) { e = ex; } assertTrue(e instanceof IndexOutOfBoundsException); }
JUnit对此具有内置支持,并带有" expected"属性
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
使用预期的异常时要小心,因为它仅断言该方法引发了该异常,而不是测试中的特定代码行。
我倾向于将其用于测试参数验证,因为此类方法通常非常简单,但最好将更复杂的测试用于:
try { methodThatShouldThrow(); fail( "My method didn't throw when I expected it to" ); } catch (MyException expectedException) { }
运用判断。
编辑现在,JUnit5已发布,最好的选择是使用Assertions.assertThrows()
(请参阅我的其他答案)。
如果尚未迁移到JUnit 5,但可以使用JUnit 4.7,则可以使用ExpectedException
规则:
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)好得多,因为如果在foo.doStuff()之前抛出IndexOutOfBoundsException,则测试将失败。
详情请参阅这篇文章