管理不同JUnit测试中的已检查异常

时间:2015-05-01 08:21:18

标签: java unit-testing junit junit4 checked-exceptions

我正在为我的一个方法编写Java Unit测试。方法声明如下:

public int convertToInteger() throws InvalidRomanNumberException
{
    int result=0;
    BaseRomanNumeral num1, num2; 
    int i=0;
    if(!validOperation())
        throw new InvalidRomanNumberException();
}

现在我正在尝试编写两个单元测试。一种是测试是否抛出了正确的异常。另一个是确保写入转换发生。这就是我的测试用例的样子

@Test
public void testRomanNumberConversion() {
    String romanValue="MCMII";
    RomanNumber num=new RomanNumber(romanValue);
    assertEquals(1903,num.convertToInteger());  
}

@Test(expected = InvalidRomanNumberException.class)
public void testInvalidRomanNumberExceptionThrown()  {
    String romanValue="MCMIIII";
    RomanNumber num=new RomanNumber(romanValue);
    num.convertToInteger(); 
}

对于这两个测试用例,我收到一条错误,指出Unhandled InvalidRomanNumberException。仅当我向每个方法定义添加抛出InvalidRomanNumberException时才解决此问题。但我认为这不是正确的方法。只想和其他人核实,这里有什么规范?我该如何解决这个未处理的异常消息

2 个答案:

答案 0 :(得分:3)

由于看起来InvalidRomanNumberException是一个经过检查的例外,您必须用try-catch包围它,或者声明方法throws InvalidRomanNumberExceptionJUnit与否,这是常态。

话虽如此,expect将抛出InvalidRomanNumberException的测试用例方法理想情况下应该声明它为throws,因为没有点用{{1}来抑制它因为你的测试用例会失败。另一方面,您期望不会抛出异常的测试用例方法可以在try-catch方法周围使用try-catch,无论是否抛出异常,此测试用例都应该有{{} 1}}关于convertToInteger方法的预期结果。

JUnit测试用例的最终结果应该是测试通过还是失败。运行时的异常也不表示。 JUnit测试用例不得崩溃。

答案 1 :(得分:3)

这更像是应该是 un 已检查的异常,而不是已检查的异常。

回想一下两者之间的区别:已检查的异常意味着可以合理地恢复,例如丢失的文件或格式错误的URL。未经检查/运行时异常意味着无法恢复,例如除以零。

如果用户输入了无效的罗马数字,说它们可以恢复并再试一次可能没有意义 - 转换层不应该对此负责。听起来更像是应该在实例化时确定的事情。

如果您改为使自定义异常扩展RuntimeException,那么您将不需要声明它被抛出(如果您这样做,它将没有任何效果),并且您将不会在你的测试中处理它。

另一种方法是声明它会在你的测试中被抛出。这样做的好处是允许您将这些异常保留为已检查的,以确保测试不会抱怨您没有处理未被捕获或未被捕获的潜在异常。

@Test
public void testRomanNumberConversion() throws InvalidRomanNumberException {
    String romanValue = "MCMII";
    RomanNumber num = new RomanNumber(romanValue);
    assertEquals(1903, num.convertToInteger());  
}

@Test(expected = InvalidRomanNumberException.class)
public void testInvalidRomanNumberExceptionThrown() throws InvalidRomanNumberException {
    String romanValue = "MCMIIII";
    RomanNumber num = new RomanNumber(romanValue);
    num.convertToInteger(); 
}