首页 文章

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

提问于
浏览
5

如果我为一个抛出一堆异常的函数编写测试用例,我应该在我的测试方法中为这些异常添加一个throws声明,还是应该捕获每个异常 . 这是怎样的正确方法?我相信try-catch是一种更好的方法,但是在catch块中我应该打印堆栈跟踪吗?

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

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

在上面的测试用例中我刚刚添加了一个 throws AuthenticationException ,但是我想知道是否最好将异常包含在try-catch块中以及在捕获异常后我做了什么 . 我可以打印堆栈跟踪 .

我通过不将它放在'throws'子句中而是放在try / catch块中来处理意外异常 AuthenticationException .

@Test
public void testGetGroupsWithNull() {
thrown.expect(IllegalArgumentException.class);
try {
  getGroups(null);
} catch(AuthenticationExcption e) {
  Assert.fail("Authentication Exception");
}
}

5 回答

  • 1

    注释更具沟通性 .

    它表示测试期望发生的事情,而不会强迫读者阅读代码 .

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

    如果抛出任何其他异常,则表示测试失败 . 当然,测试方法签名必须反映任何可能的已检查异常,就像调用相同方法的实际代码一样 .

  • 5

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

  • 4

    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"));
          }
      }
    
  • 1

    如果JUnit测试引发意外异常,则失败 . 这就是你想要的行为 . 因此,使用try / catch块进行EVER没有意义 . 如果您期望发生异常,请使用ExpectedException规则(您可以从代码片段中明确了解该规则) . 但无论你是否期待,不要使用try / catch .

    这意味着如果您的异常是已检查的异常,则需要throws子句 . 事实上,你不希望抛出异常,只是因为你的测试调用了一个可以SUSETIMES抛出一个已检查异常的方法 . 我养成了在每一种测试方法上编写 throws Exception 的习惯 . 没有理由不这样做;而且只需要担心一件事 .

  • 0

    我只是在寻找同样的问题,因为我正在处理你的主题,我找到了单元测试最佳实践的一个很好的解释 . 从文章中略微提取可以帮助您 .

    编写自己的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));
    }
    

    我们声明测试方法抛出异常而不是抛出IOException . 如果在调用测试方法期间发生任何异常,JUnit框架将确保此测试失败 - 不需要编写自己的异常处理 .

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

    希望能有所帮助 .

相关问题