JUnit中测试异常抛出的方法
2013-08-06 22:37
218 查看
最近在做TWU关于TDD的作业,对JUnit中测试异常抛出的方法进行了一些学习和思考。
在进行单元测试的时候有的时候需要测试某一方法是否抛出了正确的异常。例如,我有一个方法,里面对一个List进行读取操作,可能会抛出IndexOutOfBoundsException,我希望在单元测试中通过测试保证该方法会正确的抛出正确类型的异常。总结起来这样的测试异常是否被正确抛出的方法有三种:
1. try…fail...catch…
这种写法看上去和实现类的写法很相似,当没有异常被抛出的时候fail方法会被调用,输出测试失败的信息。
2.@Test(expected=xxx)
这种写法看上去简单了一些,但是它有一个潜在的问题:当被标记的这个测试方法中的任何一个操作抛出了相应的异常时,这个测试就会通过。这就意味着有可能抛出异常的地方并不是我们期望的那个操作。虽然这种情况可以在写test case的时候人为的避免,但是还是有更好的方法来测试异常抛出。
3.ExpectedException Rule
这种方法除了可以指定期望抛出的异常类型之外还可以指定在抛出异常时希望同时给出的异常信息。它需要在测试之前使用Rule标记来指定一个ExpectedException,并在测试相应操作之前指定期望的Exception类型(如IndexOutOfBoundException.class)
这三种方法都可以做到测试相应的操作是否抛出了期望的异常,但是哪种方法更好更适合使用呢?我的总结是:
@Test(expected=xxx) > 根本不测异常是否正确抛出
ExpectedException > @Test(expected=xxx)
try…fail…catch > ExpectedException
我之所以认为try…fail…catch方法比ExpectedException好是因为:
1. try…fail…catch更符合一般的test function的风格,先进行某项操作,在对结果进行assert。而ExpectedException的顺序确实先指明期待的结果再进行相应的操作。
2. 虽然TDD的最佳实践是每个test function只有一个assert,但是还是在有些情况下会在同一个test function里使用多个assert来对不同的方面进行测试。但是使用ExpectedException进行异常测试后,当前的test function就结束了,如果在expect的相应操作之后还有assert的话会被自动跳过,而try…fail…catch则不会跳出当前test function, 其后面的assert依然会被顺序执行。
3. ExpectedException是JUnit提供的,因此在使用别的测试框架时这样的测试方法无效。而try/catch有更多的测试框架支持(fail也是JUnit提供的。使用别的测试框架的时候不能使用fail来给出测试失败的信息)
在进行单元测试的时候有的时候需要测试某一方法是否抛出了正确的异常。例如,我有一个方法,里面对一个List进行读取操作,可能会抛出IndexOutOfBoundsException,我希望在单元测试中通过测试保证该方法会正确的抛出正确类型的异常。总结起来这样的测试异常是否被正确抛出的方法有三种:
1. try…fail...catch…
@Test public voidtestExceptionMessage() { try { new ArrayList<Object>().get(0); fail("Expected an IndexOutOfBoundsException to be thrown"); } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) { assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0")); } }
这种写法看上去和实现类的写法很相似,当没有异常被抛出的时候fail方法会被调用,输出测试失败的信息。
2.@Test(expected=xxx)
@Test(expected= IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
这种写法看上去简单了一些,但是它有一个潜在的问题:当被标记的这个测试方法中的任何一个操作抛出了相应的异常时,这个测试就会通过。这就意味着有可能抛出异常的地方并不是我们期望的那个操作。虽然这种情况可以在写test case的时候人为的避免,但是还是有更好的方法来测试异常抛出。
3.ExpectedException Rule
@Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldTestExceptionMessage() throws IndexOutOfBoundsException { List<Object> list = new ArrayList<Object>(); thrown.expect(IndexOutOfBoundsException.class); thrown.expectMessage("Index: 0, Size: 0"); list.get(0); // execution will never get past this line }
这种方法除了可以指定期望抛出的异常类型之外还可以指定在抛出异常时希望同时给出的异常信息。它需要在测试之前使用Rule标记来指定一个ExpectedException,并在测试相应操作之前指定期望的Exception类型(如IndexOutOfBoundException.class)
这三种方法都可以做到测试相应的操作是否抛出了期望的异常,但是哪种方法更好更适合使用呢?我的总结是:
@Test(expected=xxx) > 根本不测异常是否正确抛出
ExpectedException > @Test(expected=xxx)
try…fail…catch > ExpectedException
我之所以认为try…fail…catch方法比ExpectedException好是因为:
1. try…fail…catch更符合一般的test function的风格,先进行某项操作,在对结果进行assert。而ExpectedException的顺序确实先指明期待的结果再进行相应的操作。
2. 虽然TDD的最佳实践是每个test function只有一个assert,但是还是在有些情况下会在同一个test function里使用多个assert来对不同的方面进行测试。但是使用ExpectedException进行异常测试后,当前的test function就结束了,如果在expect的相应操作之后还有assert的话会被自动跳过,而try…fail…catch则不会跳出当前test function, 其后面的assert依然会被顺序执行。
3. ExpectedException是JUnit提供的,因此在使用别的测试框架时这样的测试方法无效。而try/catch有更多的测试框架支持(fail也是JUnit提供的。使用别的测试框架的时候不能使用fail来给出测试失败的信息)
相关文章推荐
- JUnit4测试方法异常抛出实例
- net自动化测试之道API测试-测试抛出异常的方法
- eclipse中,junit对单个方法进行测试时空指针异常(java.lang.NullPointerException)
- JUnit手动设计测试方法以及与Randoop的自动生成测试的比较
- junit如何测试没有返回值的方法
- 利用反射调用方法抛出的异常如何被捕获?
- Junit测试出现空指针异常
- java继承并重写方法时抛出一样的异常或不抛异常,既不能多也不能少,范围既不能打也不能小
- JUnit测试时 get()方法测试失败
- ActiveX控件调抛出异常灾难性错误的一个解决方法
- 第六十二条:每个方法抛出的异常都要有文档
- junit测试和main方法多线程中遇到的问题
- 【Servlet+Struts2】文件下载时抛出java.lang.IllegalStateException异常的解决方法
- 【C#】52. 使用Flatten方法处理并行任务抛出的异常
- JUnit 4 如何正确测试异常
- 使用JUnit测试预期异常
- junit测试中方法不运行问题所在
- Junit测试出现异常:Exception in thread "main" java.lang.NoSuchMethodError: org.junit.runner.Description.cre
- 用Junit测试void方法
- JUnit之测试方法