2009-04-17 19 views
3

Eclipse 3.4.1からJUnitテストケースを実行しています。このテストケースでは、スレッドを開始して何らかの処理を行うクラスを作成します。テストメソッドが終了すると、Eclipseが強制的にスレッドをシャットダウンしているようです。Eclipseからスレッドを含むJUnitテストケースを実行できません

コマンドラインから同じテストを実行すると、スレッドは正しく実行されます。

どういうわけか私はEclipseでこのような問題にぶつかるのを覚えていません。これはEclipseに常に存在していたものか、3.4.xで追加したものですか?ここで

は一例です:私は、Eclipseからこのテストを実行すると

は、私は(約1800まで)CNTの数printtsを取得し、テストケースをutomatically終了されます。しかし、JUnitのTestRunnerを起動するmainメソッドを実行すると、スレッドは無期限にカウントされます。

import junit.framework.TestCase; 
import junit.textui.TestRunner; 

/** 
* This class shows that Eclipses JUnit test case runner will forcibly 
* terminate all running threads 
* 
* @author pshah 
* 
*/ 
public class ThreadTest extends TestCase { 

    static Runnable run = new Runnable() { 
    public void run() { 
     int cnt = 0; 
     while(true) System.out.println(cnt++); 
    } 
    }; 

    public void testThread() { 
    Thread t = new Thread(run); 
    t.start(); 
    } 

    public static void main(String args[]) { 
    TestRunner runner = new TestRunner(); 
    runner.run(ThreadTest.class); 
    } 
} 
+1

テスト中にあなたのスレッドに正しく参加していますか? – Kosi2801

+0

Junitはアプリケーションスレッドからの応答を得ることができないため、thread.ifからの応答を受け取っていますか? – Giridhar

+0

いくつかのコード例を教えてください。 – guerda

答えて

3

あなたのコードをJUnit NGに適合させました。同じ結果です。スレッドが強制終了されました。

public class ThreadTest { 

    static Runnable run = new Runnable() { 
    public void run() { 
     int cnt = 0; 
     while (true) 
     System.out.println(cnt++); 
    } 
    }; 

    @Test 
    public void threadRun() { 
    Thread t = new Thread(run); 
    t.start(); 
    assertEquals("RUNNABLE", t.getState().toString()); 
    } 

} 

私はコマンドラインからテストを実行するためにEclipeプラグインフォルダからのJUnitジャー(私の場合は4.3.1)を使用する場合、それはそれだ(Eclipseでそれを実行するように同じ動作をします論理:))。

コマンドラインでJUnit 4.6(ダウンロードしたばかり)をテストしましたが、短時間で停止します。 Eclipseのような全く同じ動作です。


最後の命令が実行された場合、それは殺されていることがわかりました。 JUnitの仕組みを考えると論理的です。
各テストでは、新しいオブジェクトが作成されます。テストが終わったら、それは殺されます。このテストに属するすべてが殺されます。
つまり、すべてのスレッドを停止する必要があります。

この状況でJUnitが正しく処理します。単体テストは分離して実行するのが簡単でなければなりません。したがって、テストの終わりに達すると、すべてのスレッドを終了する必要があります。

テストが終了してからassertXXX命令を実行するまで待ちます。これはスレッドをテストする正しい方法です。
しかし、注意してください:それはあなたの実行時間を殺すかもしれません!

1

この変更は、さまざまなスレッドシナリオの単体テストに望ましい結果をもたらすと考えています。

public class ThreadTest { 

static Runnable run = new Runnable() { 
public void run() { 
    int cnt = 0; 
    while (true) 
    System.out.println(cnt++); 
} 
}; 

@Test 
public void threadRun() { 
Thread t = new Thread(run); 
t.start(); 

//Run the thread, t, for 30 seconds total. 
//Assert the thread's state is RUNNABLE, once per second 
for(int i=0;i<30;i++){ 
    assertEquals("RUNNABLE", t.getState().toString()); 
    try { 
     Thread.sleep(1000);//1 second sleep 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
System.out.println("Done with my thread unit test."); 
} 
} 
+0

シンプルで機能します。場合によっては、while(t.isAlive())を実行することもできます。このようにして、あなたのスレッドをスリープ状態にして、それが必要な時間を持つようにすることができます。 –

1

これは動作しますが、あなたはあなたのスレッドに名前を付けたり、それを参照する別の方法を見つける必要があり(フォーマットがグラグラであれば申し訳ありません)。

protected boolean monitorSecondaryThread(String threadName, StringBuilder errorMessage, boolean ignoreFailSafe) { 
    int NUM_THREADS_BESIDES_SECONDARY_THREAD = 2; 
    int MAX_WAIT_TIME = 10000; 

    MyUncaughtExceptionHandler meh = new MyUncaughtExceptionHandler(); 
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); 
    for (Thread t : threadSet) { 
     t.setUncaughtExceptionHandler(meh); 
    } 

    Date start = Calendar.getInstance().getTime(); 

    boolean stillAlive = true; 
    while (stillAlive) { 
     for (Thread t : threadSet) { 
      if (t.getName().equalsIgnoreCase(threadName) && !t.isAlive()) { 
       stillAlive = false; 
      } 
     } 

     Date end = Calendar.getInstance().getTime(); 

     if (!ignoreFailSafe && (end.getTime() - start.getTime() > MAX_WAIT_TIME || Thread.activeCount() <= NUM_THREADS_BESIDES_SECONDARY_THREAD)) { 
      System.out.println("Oops, flawed thread monitor."); 
      stillAlive = false; 
     } 
    } 


    if (meh.errorCount > 0) { 
     System.out.println(meh.error); 
     errorMessage.append(meh.error); 
     return false; 
    } 

    return true; 
} 

private class MyUncaughtExceptionHandler implements UncaughtExceptionHandler { 

    public int errorCount = 0; 
    public String error = ""; 

    @Override 
    public void uncaughtException(Thread t, Throwable e) { 
     ByteArrayOutputStream bs = new ByteArrayOutputStream(); 
     PrintStream ps = new PrintStream(bs); 
     e.printStackTrace(ps); 
     error = bs.toString(); 
     errorCount++; 
    } 

} 
関連する問題