Should jUnit test cases handle default exceptions in a throws declaration or in a try catch block
如果我为一个抛出一堆异常的函数编写测试用例,我应该在我的测试方法中为这些异常添加一个throws声明,还是应该捕获每个异常。 这是怎样的正确方法? 我相信try-catch是一种更好的方法,但是在catch块中我应该打印堆栈跟踪吗?
例如,我有一个抛出
1 2 3 4 5 | @Test public void testGetGroupsWithNull() throws AuthenticationException { thrown.expect(IllegalArgumentException.class); getGroups(null); } |
在上面的测试用例中我刚刚添加了一个
我通过不将它放在'throws'子句中而是放在try / catch块中来处理意外异常
1 2 3 4 5 6 7 8 9 | @Test public void testGetGroupsWithNull() { thrown.expect(IllegalArgumentException.class); try { getGroups(null); } catch(AuthenticationExcption e) { Assert.fail("Authentication Exception"); } } |
JUnit在这里有一篇很棒的文章:https://github.com/junit-team/junit/wiki/Exception-testing this subject。
你可以做:
1 2 3 4 | @Test(expected= IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); } |
要么:
1 2 3 4 5 6 7 8 9 | @Test public void testExceptionMessage() { try { new ArrayList<Object>().get(0); fail("Expected an IndexOutOfBoundsException to be thrown"); } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) { assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0")); } } |
如果JUnit测试引发意外异常,则失败。这就是你想要的行为。所以使用try / catch块的EVER没有意义。如果您期望发生异常,请使用ExpectedException规则(您显然知道该规则,来自您的代码段)。但无论你是否期待,不要使用try / catch。
这意味着如果您的异常是已检查的异常,则需要throws子句。实际上,您通常需要在测试方法上使用throws子句,即使您不希望抛出异常,只是因为您的测试调用的方法可能会导致SUSETIMES抛出已检查的异常。我养成了在每一种测试方法上编写
使用尽可能少的代码编写规则来解决问题,您的第一个代码段获胜。所以,是的,将
注释更具沟通性。
它表示测试期望发生的事情,而不会强迫读者阅读代码。
任何单个测试应该只期望抛出一个异常,因为每个测试应该测试单个行为。单个行为只能抛出一个异常。
如果抛出任何其他异常,则表示测试失败。当然,测试方法签名必须反映任何可能的已检查异常,就像调用相同方法的实际代码一样。
我只是在寻找同样的问题,因为我正在处理你的主题,我找到了单元测试最佳实践的一个很好的解释。从文章中略微提取可以帮助您。
编写自己的catch块只是为了使测试失败,因为JUnit框架会为您处理这种情况。例如,假设您正在为以下方法编写单元测试:
1 2 3 |
这里我们有一个方法接受一个整数并返回一个整数,并在遇到错误时抛出IOException。这是编写单元测试的错误方法,它确认方法在传递七时返回三:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Don't do this - it's not necessary to write the try/catch! @Test public void foo_seven() { try { assertEquals(3, new Foo().foo(7)); } catch (final IOException e) { fail(); } } |
测试中的方法指定它可以抛出IOException,这是一个经过检查的异常。因此,除非您捕获异常或声明测试方法可以传播异常,否则单元测试将无法编译。第二种选择是首选,因为它会导致更短,更集中的测试:
1 2 3 4 5 6 | // Do this instead @Test public void foo_seven() throws Exception { assertEquals(3, new Foo().foo(7)); } |
我们声明测试方法抛出异常而不是抛出IOException。如果在调用测试方法期间发生任何异常,JUnit框架将确保此测试失败 - 不需要编写自己的异常处理。
您可以在本文中找到有关上述JUnit最佳实践的更多信息:
http://www.kyleblaney.com/junit-best-practices/
希望能有所帮助。