Java不将fail方法视为分支的结尾

时间:2013-07-01 15:58:38

标签: java junit junit4

我有一个类Game,其构造函数具有以下签名:

public Game(String[] boardState) throws InvalidStringsInputException, WrongNumberOfMarksException

junit4 testcase中有一个方法:

public static Game newGameFromStringsSuccessful(String[] input) //it is the line 9
{
    try
    {
        return new Game(input);
    }
    catch (WrongNumberOfMarksException exception)
    {
        fail("Caught exception where it shouldn't be");
    }
    catch (InvalidStringsInputException exception)
    {
        fail("Caught exception where it shouldn't be");
    }
}

我正在使用eclipse,它显示了一个错误: This method must return a result of type Game line 9 Java Problem

如果我在两个return null块的末尾插入catch,则错误消失,但我的问题不是:为什么java甚至在调用fail()方法后仍然需要它?

2 个答案:

答案 0 :(得分:3)

  

为什么即使在调用fail()方法之后java也想要它?

因为编译器不知道 fail无法正常返回。没有办法在Java中表达这一点。 fail消息调用的结尾仍然可以访问 - 因此方法的结尾也是可以访问的。

假设fail方法中存在错误,那么您最终到达方法的末尾 - 您希望发生什么?

对此最简单的解决方法是在方法结束时抛出一些运行时异常,例如: AssertionError

throw new AssertionError("fail must have returned normally!");

基本上是一个例外,说“世界是疯了,我不想再住在这里” - 这也让编译器感到高兴,因为该方法的结束不再可用。

另一种替代方法 - 这里不可用,因为你不控制fail方法 - 将声明fail方法返回某种运行时异常,此时你的catch块可以看起来像这样:

catch (InvalidStringsInputException exception)
{
    throw fail("Caught exception where it shouldn't be");
}

当然fail实现仍然是抛出异常而不是返回它,但这意味着编译器知道该catch块是绝对不会正常完成。

答案 1 :(得分:1)

Jon的回答解释了为什么编译器抱怨。但是,我建议避免这种情况的正确方法是在测试中没有try/catch。只是让异常在调用堆栈中传播并超出测试范围。 JUnit将捕获它并在测试失败的同时提供抛出异常的整个堆栈跟踪。

或者,如果您不想传播throws子句,请将异常包装在RuntimeException中,然后将其抛出。同样,这将提供堆栈跟踪以便更好地进行诊断。