2

マルチスレッドシステムの機能テストがあります。問題は、システムが System.exit を使用しているため、junit テストでこのエラーがキャッチされないことです。したがって、どこかで System.exit が呼び出された場合、別のスレッドであってもテストが失敗することを望みます。

Javaを使用しました: System.exit() を呼び出すメソッドをテストするには? System.exit で JVM が停止するのを防ぎ、代わりに ExitException をスローします。また、 http://blog.cedarsoft.com/2011/12/junit-rule-fail-tests-on-exceptionsfailed-assertions-in-other-threads/を使用して、この例外を収集しました。ExitException が失敗した後にテストを停止したい。ただし、この例外は現在のスレッドのみを停止します。ExitException をスローする前に junitThread.interrupt() を呼び出そうとしましたが、単純なテストでのみ完全に機能します。

スレッド作成コードを変更できない場合、どのスレッドでも ExitException をスローする際に junit テストを中断するにはどうすればよいですか?

4

1 に答える 1

1

なぜそれを呼び出すのSystem.exit()ですか?System.exit()そして、ユニットテストでカバーしているレベルでそれが呼び出されるのはなぜですか?

既存のコードをテストする場合、テストでプロセスを生成し、計画どおりに終了したことを確認できます。他の機能をテストしたい場合は、テスト対象のコードにそのような厄介な副作用がないように、アプリケーションをより適切に構成してください。

System.exit()ただし、一般的には、個々のスレッドが呼び出されることは、アーキテクチャが悪いことを示す強力な指標であると言えます。他のスレッドにクリーンアップの機会を与えることなく、アプリケーション全体を即座に強制終了できるスレッドがある場合、すぐにかなりの問題に遭遇する可能性があります。

また、スレッドが何らかのグローバル シャットダウン ハンドラー (テストでオーバーライドできる) を呼び出す場合、System.exit()その機能のテストに問題はありません。

更新:レガシ コードを扱うときの最初のステップはSystem.exit()、テストで置き換えることができる場所に を分離することです。たとえば、次のようなクラスを作成します。

// "Singleton" with replaceable instance
public class ShutdownHandler {
    private static ShutdownHandler instance = new ShutdownHandler();

    public static ShutdownHandler getInstance() {
        return instance;
    }

    public synchronized void shutdown() {
        // default implementation
        System.exit();
    }

    public static void setInstance(ShutdownHandler newInstance) {
        // (probably also check that this is only called in a test environment)
        instance = newInstance;
    }
}

System.exit()次に、すべての呼び出しを に置き換えますShutdownHandler.getInstance().shutdown()。これにより、アプリケーションの機能がまったく変更されることはありません。しかし、テスト内のインスタンスを、いくつかのフラグを設定し、終了する代わりに例外をスローする実装に置き換えることができShutdownHandlerます。その後、テストでそのフラグをチェックして、アプリが終了したかどうかを判断できます。

また、Robert C. Martin による "Working Effectsly With Legacy Code" をお勧めします。これは、古い混乱を管理可能なものに変える方法についてのアイデアです。

于 2013-05-28T08:51:39.740 に答える