jUnit测试用例应该在throws声明或try-catch块中处理默认异常吗



如果我为抛出一堆异常的函数编写测试用例,我应该在测试方法中为这些异常添加抛出声明,还是应该捕获每个单独的异常。正确的做法是什么?我相信try-catch是一种更好的方法,但在catch块中,我应该打印stacktrace吗?

例如,我有一个抛出AuthenticationException的方法getGroups(String name)。如果我写一个测试用例来检查当name参数为null时是否抛出了IllegalArgumentException,我该如何处理AuthenticationException?我是应该将它添加到方法的throws部分,还是应该将异常包含在try-catch块中。

@Test
public void testGetGroupsWithNull() throws AuthenticationException {
 thrown.expect(IllegalArgumentException.class);
 getGroups(null);
}

在上面的测试用例中,我只是添加了一个throws AuthenticationException,但我想知道将异常封装在try-catch块中是否更好,以及在捕获异常后应该做什么。我可以打印堆栈跟踪。

我正在处理意外的异常AuthenticationException,不是将它放在"throws"子句中,而是放在try/catch块中。

@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就在这个问题上。你可以做:
@Test(expected= IndexOutOfBoundsException.class) 
public void empty() { 
  new ArrayList<Object>().get(0); 
}

或:

@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块是没有意义的。如果您期望出现异常,请使用ExpectedException规则(您显然从代码片段中了解该规则)。但无论你是否期待,都不要使用try/catch。

这意味着,如果您的异常是已检查异常,则需要一个throws子句。事实上,您经常需要在测试方法上使用throws子句,即使您不希望抛出异常,因为您的测试调用的方法有时会抛出已检查的异常。我已经养成了在每一种测试方法上都写throws Exception的习惯。没有理由不这样做;这只是少了一件需要担心的事情。

注释更具交流性。

它表示测试期望在不强制读取器读取代码的情况下发生什么。

任何一个测试都应该只期望抛出一个异常,因为每个测试都应该测试一个行为。单个行为只能引发一个异常。

如果抛出任何其他异常,则表示测试失败。测试方法签名必须反映任何可能的检查异常,当然,调用相同方法的real代码也是如此。

使用写尽可能少的代码来解决问题的规则,您的第一个代码片段将获胜。因此,是的,将AuthenticationException放入测试方法的throws子句中。它更简洁易读。

由于我正在处理您的主题,所以我一直在寻找相同的问题,并且我找到了单元测试最佳实践的良好解释。从文章中摘录一些内容可以帮助你。

没有必要编写自己的catch块,因为JUnit框架会为您处理这种情况,所以这些块的存在只会导致测试失败。例如,假设您正在为以下方法编写单元测试:

final class Foo {
  int foo(int i) throws IOException;
}

这里我们有一个方法,它接受一个整数并返回一个整数,如果遇到错误则抛出IOException。以下是编写单元测试的错误方法,该方法在通过七次测试时确认返回三次:

// 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,这是一个已检查的异常。因此,除非捕获异常或声明测试方法可以传播异常,否则单元测试不会编译。第二种选择是首选的,因为它可以缩短测试时间,提高测试重点:

// Do this instead
@Test
public void foo_seven() throws Exception
{
  assertEquals(3, new Foo().foo(7));
}

我们声明测试方法抛出Exception,而不是抛出IOException。如果在调用被测方法的过程中发生任何异常,JUnit框架将确保该测试失败——不需要编写自己的异常处理。

您可以在本文中找到更多关于JUnit最佳实践的信息,如上文所述:http://www.kyleblaney.com/junit-best-practices/

希望能帮忙。

最新更新