您的位置:軟件測試 > 開源軟件測試 > 開源單元測試工具 > junit
Junit單元測試多線程的問題
作者:Mr.Yanphet 發(fā)布時間:[ 2016/8/18 11:24:34 ] 推薦標(biāo)簽:多線程 Junit 單元測試

  下午很快完成了一個接口的監(jiān)控功能,然后屁顛屁顛地用Junit開始單元測試。然后我開始陷入崩潰的邊緣...
  監(jiān)控結(jié)束后需要將監(jiān)控結(jié)果以郵件的形式發(fā)送給運(yùn)營的小伙伴維護(hù),前面測試還是很順利,到了開多線程發(fā)郵件時不行了,
  程序也不報錯,也接收不到郵件。然后改代碼再測試,再冥思一會兒,再改再測試,還是無果,后選擇度娘一下,結(jié)論是:
  Junit單元測試不支持多線程
  然后,整個人都不好了...浪費(fèi)了我好多時間,是因為這個。!
  雖然知道了結(jié)果,但是筆者還是需要親自驗證一下。
/**
* @Title: TestDoWork.java
* @Describe:
* @author: Mr.Yanphet
* @Email: mr_yanphet@163.com
* @date: 2016年8月15日 下午5:50:03
* @version: 1.0
*/
public class TestDoWork {
class DoWork implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
long milliSecond = System.currentTimeMillis();
System.out.println("i=" + i + ",milliSecond=" + milliSecond);// 輸出循環(huán)次數(shù)和當(dāng)前的系統(tǒng)時間
}
}
}
@Test
public void test() {
DoWork dw = new DoWork();
Thread t = new Thread(dw);
t.start();
}
}
  輸出結(jié)果如下(筆者省略了部分輸出):
  .....
  i=751,milliSecond=1471257586416
  i=752,milliSecond=1471257586416
  i=753,milliSecond=1471257586416
  i=754,milliSecond=1471257586416
  i=755,milliSecond=1471257586416
  i=756,milliSecond=1471257586416
  i=757,milliSecond=1471257586416
  i=758,milliSecond=1471257586416
  從結(jié)果可以看到,循環(huán)到了759次后沒再輸出了,說明子線程還沒結(jié)束任務(wù),整個程序被強(qiáng)迫結(jié)束了。
  既然知道了現(xiàn)象,那么為什么會出現(xiàn)這樣的現(xiàn)象呢,貼出部分Junit4 TestRunner源碼知道了
public static final int SUCCESS_EXIT = 0;
public static final int FAILURE_EXIT = 1;
public static final int EXCEPTION_EXIT = 2;
public static void main(String args[]) {
TestRunner aTestRunner = new TestRunner();
try {
TestResult r = aTestRunner.start(args);
if (!r.wasSuccessful())
System.exit(FAILURE_EXIT);
System.exit(SUCCESS_EXIT);
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
  再貼上TestResult部分源碼,以供參考
protected  List<TestFailure>    fFailures
protected  List<TestFailure>    fErrors
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
public synchronized int errorCount() {
return fErrors.size();
}
public synchronized int failureCount() {
return fFailures.size();
}
  在TestRunner中可以看出,如果是單線程,當(dāng)測試主線程執(zhí)行結(jié)束后,不管子線程是否結(jié)束,都會回調(diào)TestResult的wasSuccessful方法,
  然后判斷結(jié)果是成功還是失敗,后調(diào)用相應(yīng)的System.exit()方法。大家都知道這個方法是用來結(jié)束當(dāng)前正在運(yùn)行中的java虛擬機(jī),jvm都
  自身難保了,所以子線程也對不住你咧...
  解決辦法:
  1 簡單粗暴地讓主線程休眠一段時間,然后讓子線程能夠運(yùn)行結(jié)束。但是這個方法的弊端是,你不知道子線程的運(yùn)行時間,所以需要看臉=_=
  Thread.sleep();
  2 使用CountDownLatch工具類,讓主線程阻塞,直到子線程運(yùn)行結(jié)束或者阻塞超時,這個方法要比第一個方法好點(diǎn)。
  countDownLatch.await(5, TimeUnit.MINUTES);
  至于還有其他方法,筆者看到很多大神自己寫的Junit支持多線程,有興趣的讀者自行度娘...

軟件測試工具 | 聯(lián)系我們 | 投訴建議 | 誠聘英才 | 申請使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd