在下面的代码中,ClassToTest.throwsException()引发了一个已检查的异常。我的偏好是将抛出异常添加到JUnit方法签名中,而不是将尝试抛出异常的代码包装在try catch中。这种偏好仅基于我认为更整洁的事实。我在这里违反编码规范吗?从测试的角度来看,在测试方法中引发异常与try / catch的功能是否有所不同?
import org.junit.Test;
public class TestingClass {
@Test
public void getDataTest() throws Exception {
new ClassToTest().throwsException();
}
}
与:
import org.junit.Test;
public class TestingClass {
@Test
public void getDataTest() {
try {
new ClassToTest().throwsException();
} catch (Exception e) {
e.printStackTrace();
}
}
}
ClassToTest.java:
public class ClassToTest {
public void throwsException() throws Exception {
}
}
答案 0 :(得分:2)
只需将throws
子句添加到方法声明中,并使异常冒泡,如JUnit4 FAQ - How do I write a test that fails when an unexpected exception is thrown?中所述:
在测试方法的
throws
子句中声明异常,并且不要在测试方法中捕获该异常。未捕获的异常将导致测试失败并显示错误。下面是一个示例测试,当引发
IndexOutOfBoundsException
时失败:@Test public void testIndexOutOfBoundsExceptionNotRaised() throws IndexOutOfBoundsException { ArrayList emptyList = new ArrayList(); Object o = emptyList.get(0); }
IndexOutOfBoundsException
在这里可能不是一个很好的例子,因为它是RuntimeException
,但是对于其他例外情况,方法是相同的。
答案 1 :(得分:2)
如果不希望抛出Exception
,则在代码中添加try-catch
块没有任何额外的好处。更糟糕的是,仅添加try-catch
块会导致测试通过。要使测试失败,必须向fail()
添加一个调用才能使测试实际失败。这可能是错误的来源(如果有人忘记打电话给fail()
)。
出于完整性考虑,我将简短地讨论如何验证是否抛出了某个Exception
。我想到了三种方法。
第一次尝试时,可以使用try-catch
,但是在应该抛出预期的fail()
的调用之后的try
块中添加了Exception
。然后,在catch
块中,将捕获预期的Exception
。所有其他Exception
将被重新抛出,因此测试将失败。它具有与上述同级产品相同的缺点。
第二,通过使用@Test(expected = ExpectedException.class)
注释测试本身,存在JUnit4方式。乍一看似乎很整洁,但是却破坏了Given-When-Then structure测试,常常导致如下所示的测试:
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void test() {
// GIVEN
final int[] array = new int[10];
// WHEN
final int value = array[10];
// THEN: an ArrayIndexOutOfBoundsException should be thrown
}
没关系。
最后,通过将实际调用包装到assertThrows(...)
的调用中,可以使用JUnit5:
@Test(expected = ArrayIndexOutOfBoundsException.class)
void test() {
// GIVEN
final int[] array = new int[10];
// WHEN
final Exception e = assertThrows(ArrayIndexOutOfBoundsException.class,
() -> {
int value = array[10];
}
);
// THEN
assertTrue(e.getMessage().contains("10"));
}
尽管这仍然不能正确地将WHEN
与THEN
分开(我认为这在Java中是不可能的),但它提供了额外的好处,允许检查{{1}的特定部分},例如消息 1 。
我建议this article over at Baelung作为进一步阅读。
1 这在JUnit4中也是可能的,但是可以通过显式的Exception
块或非常笨拙的机制来完成,该机制最终会破坏“ Given-When-Then”结构。有关更多信息,请查阅上面提到的Baelung上的文章。