Java 如何断言捕获了异常?

Java 如何断言捕获了异常?,java,junit,exception-handling,Java,Junit,Exception Handling,我知道如何断言抛出了异常。但是,我怎样才能断言抛出了异常并成功捕获了它呢?例如,假设我有一个方法,该方法应该为无效输入抛出特定类型的异常 public static void myMethod(String value) { try { someExternalMethod(value);// can throw IllegalArgumentException } catch (IllegalArgumentException e) { Syst

我知道如何断言抛出了异常。但是,我怎样才能断言抛出了异常并成功捕获了它呢?例如,假设我有一个方法,该方法应该为无效输入抛出特定类型的异常

public static void myMethod(String value) {
    try {
        someExternalMethod(value);// can throw IllegalArgumentException
    } catch (IllegalArgumentException e) {
        System.out.println("Let me handle it differently");
    } catch (Exception e) {
        System.out.println("Not IllegalArgumentException");
    }
}

现在我想断言,对于某些值,该方法确实抛出了“IllegalArgumentException”,而不是其他一些异常。

catch
块是按照它们的顺序计算的


您的代码工作正常:在出现
IllegalArgumentException
的情况下,
异常
块将被忽略。

在测试
myMethod
的上下文中,您不能(更重要的是,您不应该)检查
某个外部方法
是否引发了
IllegalArgumentException
。事实上,您对
myMethod
的测试不应该假设调用了
someExternalMethod
:这是
myMethod
的一个实现细节

myMethod
捕获这些异常的原因就是对其调用者隐藏它们。您应该通过传递导致这些异常的值并验证在这两种情况下都没有抛出任何异常来检查这些异常是否对您隐藏


测试
someExternalMethod
,以及它引发的异常,是通过测试
someExternalMethod
,而不是
myMethod

,来完成的任务。您错过了单元测试的要点-测试应该测试行为,而不是实现。

基于此假设,当发生
IllegalArgumentException
时,您应该测试
myMethod
的行为是否符合预期。很难说,对于给定参数的方法,单个
字符串是不可变的,没有返回值,也没有抛出异常

一个更好的例子可能是这种方法(为了证明这一点有点做作):

您的测试将断言除法是正确的,并且当出现错误时,会返回
NaN
,如下所示:

@Test
public void testDivide()
{
  assertEquals(2.0, divide(4, 2), 0);
}

@Test
public void testDivideByZero()
{
  assertTrue(Double.isNaN(divide(1, 0));
}
public double divide(int numerator, int denominator)
{
  if (denominator == 0)
  {
    return Double.NaN;
  }
  else
  {
    return numerator / denominator;
  }
}
然后可以像这样重新编写
divide
方法:

@Test
public void testDivide()
{
  assertEquals(2.0, divide(4, 2), 0);
}

@Test
public void testDivideByZero()
{
  assertTrue(Double.isNaN(divide(1, 0));
}
public double divide(int numerator, int denominator)
{
  if (denominator == 0)
  {
    return Double.NaN;
  }
  else
  {
    return numerator / denominator;
  }
}
测试将确认我的系统的运行,因为
divide
方法的行为保持不变

  • Mock方法
    someExternalMethod(value)
    强制抛出
    异常
  • 测试方法
    myMethod
    ,检查是否未引发异常:

    @Test
    public void testMyMethod() {
       try {
          myMethod("value");
       } catch (Exception ex) {
          Assert.fail();
       }
    }
    

  • 对于相同的输入,首先测试
    someExternalMethod
    是否抛出异常,然后测试
    myMethod
    是否抛出异常?您可以模拟方法来抛出异常。@tobias_k:虽然我为简单起见编写了
    someExternalMethod
    ,但我调用实际方法的方式有点不同,我正在使用一些深度重试策略,使用执行器来调用它。但我明白你的正确观点,可能是如果我没有其他选择,我必须改变我的测试方式。这个问题可能是重复的。“Nan”不等于它本身吗?@C.R。事实上,在IDE中玩这个例子时,逻辑并不完全正确(我确实说过它是有点刻意证明这一点的)断言中应该使用
    Double.isNaN