4

特定の Java アプリケーションをテストしようとしていますが、そのために JUnit を使用したいと考えています。

私が直面している問題は次のとおりです。テストしようとしているコードが作業System.exit()を終了すると、アプリケーションが終了します。JVMを閉じる​​ため、テストの完了も停止していますが(私は推測しています)。

元のコードを変更せずに、この問題を回避する方法はありますか? 最初に、新しいスレッドからテストするアプリケーションを起動しようとしましたが、明らかに大きな違いはありませんでした。

4

3 に答える 3

11

システム ルールを使用できますjava.lang.System。「を使用するコードをテストするための JUnit ルールのコレクション」。

それらのルールの中で、あなたはExpectedSystemExitそれを使用する方法の例を以下に示します。とてもクリーンなソリューションだと思います。

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.Assertion;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;

public class SystemExitTest {
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void noSystemExit() {
        //passes
    }

    @Test
    public void executeSomeCodeAFTERsystemExit() {
        System.out.println("This is executed before everything.");
        exit.expectSystemExit();
        exit.checkAssertionAfterwards(new Assertion() {
            @Override
            public void checkAssertion() throws Exception {
                System.out.println("This is executed AFTER System.exit()"+
                " and, if exists, the @org.junit.After annotated method!");
            }
        });
        System.out.println("This is executed right before System.exit().");
        System.exit(0);
        System.out.println("This is NEVER executed.");
    }

    @Test
    public void systemExitWithArbitraryStatusCode() {
        exit.expectSystemExit();
        System.exit(0);
    }

    @Test
    public void systemExitWithSelectedStatusCode0() {
        exit.expectSystemExitWithStatus(0);
        System.exit(0);
    }

    @Test
    public void failSystemExit() {
        exit.expectSystemExit();
        //System.exit(0);
    }

}

Maven を使用する場合は、これを に追加できますpom.xml

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
</dependency>
<dependency>
    <groupId>com.github.stefanbirkner</groupId>
    <artifactId>system-rules</artifactId>
    <version>1.3.0</version>
</dependency>
于 2013-04-13T23:14:00.210 に答える
3

System.exit(status)実際に呼び出しをRuntimeクラスに委譲します。このシャットダウン要求を続行する前のランタイムは、 SecurityExceptionをスローすることで差し迫ったシャットダウンを防ぐことができるcheckExit(status)JVM の現在のSecurityManagerを呼び出します。

通常、SecurityManagerは、現在のスレッドが現在のセキュリティ ポリシーによって定義されたシャットダウンの特権を持っているかどうかを確認する必要がありますが、必要なのはこの終了呼び出しから回復することだけなので、ここでキャッチする必要があるSecurityExceptionをスローするだけです。私たちのJUnitテストケース。

JUnit テスト クラスで、メソッドにSecurityManagerをセットアップします。setUP()

    securityManager = System.getSecurityManager();
    System.setSecurityManager(new SecurityManager() {
        @Override
        public void checkExit(int status) {
            super.checkExit(status); // This is IMPORTANT!
            throw new SecurityException("Overriding shutdown...");
        }
    });

SecurityManagerを、前に保存したインスタンスに再度tearDown()置き換えます。そうしないと、JUnit がすぐにシャットダウンできなくなります。:)

参照:
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/SecurityManager.html
http://docs.oracle.com/javase/1.5.0/docs/api/java /lang/SecurityManager.html#checkExit(int)

SecurityManager クラスには、単語 check で始まる名前のメソッドが多数含まれています。これらのメソッドは、潜在的に機密性の高い特定の操作を実行する前に、Java ライブラリのさまざまなメソッドによって呼び出されます。このようなチェック メソッドの呼び出しは、通常、次のようになります。

     SecurityManager security = System.getSecurityManager();
     if (security != null) {
         security.checkXXX(argument,  . . . );
     }

これにより、セキュリティ マネージャには、例外をスローして操作の完了を防止する機会が与えられます。セキュリティ マネージャ ルーチンは、操作が許可されている場合は単純に戻りますが、操作が許可されていない場合は SecurityException をスローします。

于 2013-04-14T01:01:08.637 に答える