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

Java jUnit测试用例应该在throws声明或try-catch块中处理默认异常吗,java,exception,junit,Java,Exception,Junit,如果我为抛出一组异常的函数编写测试用例,我应该在测试方法中为这些异常添加一个抛出声明,还是捕获每个异常。正确的做法是什么?我相信try-catch是一种更好的方法,但是在catch块中我应该打印stacktrace吗 例如,我有一个方法getGroups(stringname),它抛出AuthenticationException。如果我编写一个测试用例来检查name参数为null时是否抛出IllegalArgumentException,我如何处理AuthenticationException

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

例如,我有一个方法
getGroups(stringname)
,它抛出
AuthenticationException
。如果我编写一个测试用例来检查
name
参数为null时是否抛出
IllegalArgumentException
,我如何处理
AuthenticationException
?我是将其添加到方法的抛出部分,还是将异常包含在
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在这里有一篇很棒的文章:关于这个主题。 你可以做:

@Test(expected= IndexOutOfBoundsException.class) 
public void empty() { 
  new ArrayList<Object>().get(0); 
}
@Test(预期=IndexOutOfBoundsException.class)
public void empty(){
新建ArrayList().get(0);
}
或:

@测试
public void testExceptionMessage(){
试一试{
新建ArrayList().get(0);
失败(“预期将抛出IndexOutOfBoundsException”);
}catch(IndexOutOfBoundsException和IndexOutOfBoundsException){
断言(IndexOutofBoundsException.getMessage()是(“索引:0,大小:0”);
}
}

注释更具沟通性

它发出测试预期发生的信号,而不强制读者阅读代码

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


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

如果JUnit测试抛出意外异常,它将失败。这就是你想要的行为。因此,永远不要使用try/catch块。如果您预期会出现异常,请使用ExpectedException规则(您显然从代码片段中了解该规则)。但是,不管你是否期待,都不要使用try/catch


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

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

我只是在寻找同样的问题,因为我正在处理您的主题,并且我找到了一个关于单元测试最佳实践的很好的解释。从这篇文章中摘录一点可以帮助你

没有必要编写您自己的catch块,因为JUnit框架会为您解决这一问题,而这些catch块的存在只会导致测试失败。例如,假设您正在为以下方法编写单元测试:

final class Foo {
  int foo(int i) throws IOException;
}
这里我们有一个方法,它接受一个整数并返回一个整数,如果遇到错误则抛出一个IOException。下面是一种错误的编写单元测试的方法,该测试确认方法在通过7次时返回3次:

// 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));
}
我们声明测试方法抛出异常,而不是抛出IOException。JUnit框架将确保如果在调用被测方法的过程中发生任何异常,则该测试将失败-无需编写自己的异常处理

您可以在本文中找到更多关于上述JUnit最佳实践的信息:


希望能帮上忙。

我只是想确定我明白你的意思。在这种特殊情况下或一般情况下,由于
AuthenticationException
是一个选中的异常,我应该将该异常添加到方法的'throws'子句中。我不应该在try/catch块中处理此异常,因为即使抛出了
AuthenticationException
,测试用例也会通过。在这种特殊情况下,如果您确实处理了异常,除了通过
ExpectedException
规则处理它之外,那么测试将失败。这是因为
ExpectedException
规则用于确保异常确实被抛出,而不是被捕获。因此,不要在这个测试方法中使用try/catch,否则它将失败。而且,一般来说,不要在任何测试方法中使用try/catch,因为没有必要这样做,它只会给测试增加噪音。我现在有点困惑。但是,您不是说过当发生意外异常时,JUnit测试会失败吗。因此,如果我在方法的throws子句中添加
AuthenticationException
,即使抛出意外异常,测试用例也会通过。另一方面,如果我在try/catch块中处理意外异常,并强制测试方法抛出意外的exc
// Do this instead
@Test
public void foo_seven() throws Exception
{
  assertEquals(3, new Foo().foo(7));
}