2009-04-17 61 views
3

我正在從Eclipse 3.4.1運行JUnit測試用例。這個測試用例創建了一個啓動線程來完成某些任務的類。當測試方法結束時,似乎Eclipse正在強制關閉該線程。無法運行包含來自Eclipse的線程的JUnit測試用例

如果我從命令行運行相同的測試,則線程正常運行。

不知何故,我不記得以前遇到過這樣的Eclipse問題。這是一直存在於Eclipse中的東西還是他們在3.4.x中添加的?

下面是一個例子:

當我從Eclipse運行這個測試,我得到的CNT(直到約1800)的幾個printts然後測試用例utomatically終止。但是,如果我運行啓動JUnit的TestRunner的主方法,那麼線程將不確定地計數。

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 2009-04-17 13:30:25

+0

您是否從thread.ne獲取響應,請不要讓我知道。因爲Junit不具備從應用程序線程獲取響應的能力。 – Giridhar 2009-04-21 15:41:54

回答

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()); 
    } 

} 

如果我使用(在我的情況4.3.1)JUnit的罐子從插件的Eclipe文件夾通過命令行來執行測試,它就像在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."); 
} 
} 
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++; 
    } 

}