策略模式:当并非所有方法都抛出异常时,抑制 JUnit 中特定测试的异常警告

问题描述

示例代码

public Interface FlightBehavIoUr {
    void fly();
}

public class Fly implements FlightBehavIoUr {
    @Override
    public void fly() throws CrashWithObject {
        // does something to fly
    }
}

public class CanNotFly implements FlightBehavIoUr {
    @Override
    public void fly() {
        // does not fly
    }
}

public class Bird() {
    private FlightBehavIoUr fly;
    
    public void setFlightBehavIoUr(FlightBehavIoUr flightBehavIoUr) {
        this.car = car;
    }

    @Override
    public void fly() throws CrashWithObject {
        car.fly();
    }
}

JUnit:

@Test
public void testFlighBehavIoUrOfNonFlyingBird() {
    // ...
    Bird plasticDuck = new Bird();
    plasticDuck.setFlightBehavIoUr(new CanNotFly());
    plasticDuck.fly(); //Compiler shows that an Exception is thrown
    // However,I kNow that this will never happen since my Bird can't fly 
    // and therefore never throws an exception
    // ...
}

这是我的实现的简单复制。如您所见,我正在使用策略模式。

我的问题是:如何抑制给出的警告?

解决方法

在测试用例中,你不应该假设不能抛出异常,而是测试它(通过在异常的情况下使测试失败,也许是在试图引发它)。

使用您的(基于策略模式的)代码结构,编译器几乎不可能推断不会抛出异常。作为人类,我们已经面临着这种推理的艰巨工作(忽略代码中的一些错别字):

  • Bird.fly() 方法仅在 CrashWithObject 抛出时才会抛出 fly.fly()
  • fly 最近被设置为 CannotFly 中的 plasticDuck.setFlightBehaviour(new CanNotFly());
  • CannotFly.fly() 不会抛出 CrashWithObject
  • 可能没有为此 setFlightBehaviour() 实例在其他任何地方调用 Bird,但这需要对整个应用程序进行彻底分析才能真正确定这一点。
  • 因此,我们希望 fly 字段在 CannotFly 调用时仍保持 plasticDuck.fly() 的实例,这使我们可以得出结论,没有 CrashWithObject 可以是抛出。

你看,它需要对各种代码片段进行大量非平凡的推理才能得出无例外的结论,这是我不希望很快在编译器中看到的深度推理。